From 5524cacdd1c1d0b8a659e0742148d112b4f71ef4 Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Mon, 7 Sep 2026 22:46:00 -0700 Subject: [PATCH 01/11] feat(competitors): add aspose-foss + zavora adapters, Tier 4, mutation + calc lanes - aspose-cells-foss adapter (Python lane, 'aspose' extra): 11/22 green - zavora-xlsx external-oracle adapter (cross-language lane) + Rust helper; upstream 0.1.2 defects scored honestly (hyperlink rel corruption, no recalc) - Tier 4 fidelity features (sheet_protection, page_setup, chart_anchor) with openpyxl-structural fixtures; 22 scored features total - wolfxl adapter ported to WolfXL 2.1.0 public API (19/22; CF-read and print-title-write gaps recorded) - Template-mutation lane: wall time, peak RSS, package preservation - Calc tier: cache-free 133-formula financial DAG fixture, LibreOffice oracle, strict pass/fail semantics - CLI: 'excelbench mutation' and 'excelbench calc'; zavora in cross-language lane - Snapshot artifacts: results-2026-09-08/{xlsx,mutation,calc,cross-language} - Docs: DEC-023..DEC-026, README tables, METHODOLOGY, TRACKER, architecture Verification: uv run pytest (1235 passed, 79 skipped, 6 xfailed); ruff clean. --- CLAUDE.md | 9 + METHODOLOGY.md | 48 +- README.md | 85 +- TRACKER.md | 26 +- architecture.md | 12 +- decisions.md | 135 + docs/public-reporting.md | 6 + fixtures/calc/expected_values.json | 537 + fixtures/calc/financial_model.xlsx | Bin 0 -> 9159 bytes fixtures/excel/manifest.json | 181 +- fixtures/excel/tier4/20_sheet_protection.xlsx | Bin 0 -> 6382 bytes fixtures/excel/tier4/21_page_setup.xlsx | Bin 0 -> 6231 bytes fixtures/excel/tier4/22_chart_anchor.xlsx | Bin 0 -> 7046 bytes fixtures/mutation/manifest.json | 64 + .../mutation/template_corporate_model.xlsx | Bin 0 -> 15043 bytes pyproject.toml | 7 +- results-2026-09-08/calc/README.md | 18 + .../aspose_cells_foss/financial_model.xlsx | Bin 0 -> 9655 bytes .../calc/libreoffice/financial_model.xlsx | Bin 0 -> 13135 bytes results-2026-09-08/calc/results.json | 187 + .../calc/wolfxl/financial_model.xlsx | Bin 0 -> 9894 bytes .../calc/zavora/financial_model.xlsx | Bin 0 -> 9022 bytes results-2026-09-08/cross-language/CONTEXT.md | 20 + .../cross-language/FIDELITY_DELTAS.md | 3 + results-2026-09-08/cross-language/README.md | 451 + .../cross-language/WHY_FAILED.md | 421 + .../cross-language/history.jsonl | 1 + results-2026-09-08/cross-language/matrix.csv | 23 + .../cross-language/results.json | 4326 + results-2026-09-08/mutation/README.md | 19 + .../aspose-cells-foss/repeat-1-input.xlsx | Bin 0 -> 15042 bytes .../aspose-cells-foss/repeat-1-output.xlsx | Bin 0 -> 14832 bytes .../aspose-cells-foss/repeat-2-input.xlsx | Bin 0 -> 15042 bytes .../aspose-cells-foss/repeat-2-output.xlsx | Bin 0 -> 14832 bytes .../aspose-cells-foss/repeat-3-input.xlsx | Bin 0 -> 15042 bytes .../aspose-cells-foss/repeat-3-output.xlsx | Bin 0 -> 14832 bytes .../mutation/openpyxl/repeat-1-input.xlsx | Bin 0 -> 15042 bytes .../mutation/openpyxl/repeat-1-output.xlsx | Bin 0 -> 14099 bytes .../mutation/openpyxl/repeat-2-input.xlsx | Bin 0 -> 15042 bytes .../mutation/openpyxl/repeat-2-output.xlsx | Bin 0 -> 14100 bytes .../mutation/openpyxl/repeat-3-input.xlsx | Bin 0 -> 15042 bytes .../mutation/openpyxl/repeat-3-output.xlsx | Bin 0 -> 14100 bytes results-2026-09-08/mutation/results.json | 743 + .../mutation/wolfxl/repeat-1-input.xlsx | Bin 0 -> 15042 bytes .../mutation/wolfxl/repeat-1-output.xlsx | Bin 0 -> 15726 bytes .../mutation/wolfxl/repeat-2-input.xlsx | Bin 0 -> 15042 bytes .../mutation/wolfxl/repeat-2-output.xlsx | Bin 0 -> 15726 bytes .../mutation/wolfxl/repeat-3-input.xlsx | Bin 0 -> 15042 bytes .../mutation/wolfxl/repeat-3-output.xlsx | Bin 0 -> 15726 bytes .../mutation/zavora-xlsx/repeat-1-input.xlsx | Bin 0 -> 15042 bytes .../mutation/zavora-xlsx/repeat-1-output.xlsx | Bin 0 -> 14211 bytes .../mutation/zavora-xlsx/repeat-2-input.xlsx | Bin 0 -> 15042 bytes .../mutation/zavora-xlsx/repeat-2-output.xlsx | Bin 0 -> 14211 bytes .../mutation/zavora-xlsx/repeat-3-input.xlsx | Bin 0 -> 15042 bytes .../mutation/zavora-xlsx/repeat-3-output.xlsx | Bin 0 -> 14211 bytes results-2026-09-08/xlsx/FIDELITY_DELTAS.md | 3 + results-2026-09-08/xlsx/README.md | 4025 + results-2026-09-08/xlsx/WHY_FAILED.md | 8497 ++ results-2026-09-08/xlsx/history.jsonl | 1 + results-2026-09-08/xlsx/matrix.csv | 309 + results-2026-09-08/xlsx/results.json | 81010 ++++++++++++++++ scripts/build_calc_fixture.py | 286 + scripts/build_mutation_template.py | 293 + scripts/build_tier4_fixtures.py | 286 + src/excelbench/cli.py | 272 +- src/excelbench/harness/adapters/__init__.py | 68 +- .../adapters/aspose_cells_foss_adapter.py | 866 + src/excelbench/harness/adapters/base.py | 89 +- .../harness/adapters/openpyxl_adapter.py | 231 +- .../harness/adapters/wolfxl_adapter.py | 1217 +- .../harness/adapters/zavora_adapter.py | 331 + src/excelbench/harness/calc.py | 439 + src/excelbench/harness/external_oracles.py | 53 +- src/excelbench/harness/mutation.py | 364 + src/excelbench/harness/runner.py | 271 +- src/excelbench/modifiable.py | 194 + src/excelbench/results/calc_renderer.py | 62 + src/excelbench/results/mutation_renderer.py | 81 + tests/test_aspose_cells_foss_adapter.py | 125 + tests/test_calc_suite.py | 86 + tests/test_external_oracles.py | 3 + tests/test_mutation_suite.py | 195 + tests/test_tier4_handlers.py | 206 + tests/test_zavora_adapter.py | 123 + tools/external-oracles/zavora/.gitignore | 1 + tools/external-oracles/zavora/Cargo.toml | 14 + tools/external-oracles/zavora/src/main.rs | 723 + uv.lock | 60 +- 88 files changed, 107714 insertions(+), 392 deletions(-) create mode 100644 fixtures/calc/expected_values.json create mode 100644 fixtures/calc/financial_model.xlsx create mode 100644 fixtures/excel/tier4/20_sheet_protection.xlsx create mode 100644 fixtures/excel/tier4/21_page_setup.xlsx create mode 100644 fixtures/excel/tier4/22_chart_anchor.xlsx create mode 100644 fixtures/mutation/manifest.json create mode 100644 fixtures/mutation/template_corporate_model.xlsx create mode 100644 results-2026-09-08/calc/README.md create mode 100644 results-2026-09-08/calc/aspose_cells_foss/financial_model.xlsx create mode 100644 results-2026-09-08/calc/libreoffice/financial_model.xlsx create mode 100644 results-2026-09-08/calc/results.json create mode 100644 results-2026-09-08/calc/wolfxl/financial_model.xlsx create mode 100644 results-2026-09-08/calc/zavora/financial_model.xlsx create mode 100644 results-2026-09-08/cross-language/CONTEXT.md create mode 100644 results-2026-09-08/cross-language/FIDELITY_DELTAS.md create mode 100644 results-2026-09-08/cross-language/README.md create mode 100644 results-2026-09-08/cross-language/WHY_FAILED.md create mode 100644 results-2026-09-08/cross-language/history.jsonl create mode 100644 results-2026-09-08/cross-language/matrix.csv create mode 100644 results-2026-09-08/cross-language/results.json create mode 100644 results-2026-09-08/mutation/README.md create mode 100644 results-2026-09-08/mutation/aspose-cells-foss/repeat-1-input.xlsx create mode 100644 results-2026-09-08/mutation/aspose-cells-foss/repeat-1-output.xlsx create mode 100644 results-2026-09-08/mutation/aspose-cells-foss/repeat-2-input.xlsx create mode 100644 results-2026-09-08/mutation/aspose-cells-foss/repeat-2-output.xlsx create mode 100644 results-2026-09-08/mutation/aspose-cells-foss/repeat-3-input.xlsx create mode 100644 results-2026-09-08/mutation/aspose-cells-foss/repeat-3-output.xlsx create mode 100644 results-2026-09-08/mutation/openpyxl/repeat-1-input.xlsx create mode 100644 results-2026-09-08/mutation/openpyxl/repeat-1-output.xlsx create mode 100644 results-2026-09-08/mutation/openpyxl/repeat-2-input.xlsx create mode 100644 results-2026-09-08/mutation/openpyxl/repeat-2-output.xlsx create mode 100644 results-2026-09-08/mutation/openpyxl/repeat-3-input.xlsx create mode 100644 results-2026-09-08/mutation/openpyxl/repeat-3-output.xlsx create mode 100644 results-2026-09-08/mutation/results.json create mode 100644 results-2026-09-08/mutation/wolfxl/repeat-1-input.xlsx create mode 100644 results-2026-09-08/mutation/wolfxl/repeat-1-output.xlsx create mode 100644 results-2026-09-08/mutation/wolfxl/repeat-2-input.xlsx create mode 100644 results-2026-09-08/mutation/wolfxl/repeat-2-output.xlsx create mode 100644 results-2026-09-08/mutation/wolfxl/repeat-3-input.xlsx create mode 100644 results-2026-09-08/mutation/wolfxl/repeat-3-output.xlsx create mode 100644 results-2026-09-08/mutation/zavora-xlsx/repeat-1-input.xlsx create mode 100644 results-2026-09-08/mutation/zavora-xlsx/repeat-1-output.xlsx create mode 100644 results-2026-09-08/mutation/zavora-xlsx/repeat-2-input.xlsx create mode 100644 results-2026-09-08/mutation/zavora-xlsx/repeat-2-output.xlsx create mode 100644 results-2026-09-08/mutation/zavora-xlsx/repeat-3-input.xlsx create mode 100644 results-2026-09-08/mutation/zavora-xlsx/repeat-3-output.xlsx create mode 100644 results-2026-09-08/xlsx/FIDELITY_DELTAS.md create mode 100644 results-2026-09-08/xlsx/README.md create mode 100644 results-2026-09-08/xlsx/WHY_FAILED.md create mode 100644 results-2026-09-08/xlsx/history.jsonl create mode 100644 results-2026-09-08/xlsx/matrix.csv create mode 100644 results-2026-09-08/xlsx/results.json create mode 100755 scripts/build_calc_fixture.py create mode 100755 scripts/build_mutation_template.py create mode 100755 scripts/build_tier4_fixtures.py create mode 100644 src/excelbench/harness/adapters/aspose_cells_foss_adapter.py create mode 100644 src/excelbench/harness/adapters/zavora_adapter.py create mode 100644 src/excelbench/harness/calc.py create mode 100644 src/excelbench/harness/mutation.py create mode 100644 src/excelbench/modifiable.py create mode 100644 src/excelbench/results/calc_renderer.py create mode 100644 src/excelbench/results/mutation_renderer.py create mode 100644 tests/test_aspose_cells_foss_adapter.py create mode 100644 tests/test_calc_suite.py create mode 100644 tests/test_mutation_suite.py create mode 100644 tests/test_tier4_handlers.py create mode 100644 tests/test_zavora_adapter.py create mode 100644 tools/external-oracles/zavora/.gitignore create mode 100644 tools/external-oracles/zavora/Cargo.toml create mode 100644 tools/external-oracles/zavora/src/main.rs diff --git a/CLAUDE.md b/CLAUDE.md index f97702d..7e4a0a6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -43,6 +43,15 @@ uv run excelbench html # Generate fidelity-vs-throughput scatter plots uv run excelbench scatter +# Run template-mutation suite (wall time, RSS, preservation) +uv run excelbench mutation --output results/mutation + +# Run formula-recalculation tier (cache-free fixture, LibreOffice oracle) +uv run excelbench calc --output results/calc + +# Run cross-language context snapshot (POI/Excelize/zavora when built) +uv run excelbench cross-language-context --output results-cross-language + # Lint + typecheck uv run ruff check uv run mypy diff --git a/METHODOLOGY.md b/METHODOLOGY.md index 32ba4bc..82fcccc 100644 --- a/METHODOLOGY.md +++ b/METHODOLOGY.md @@ -28,6 +28,15 @@ This allows reliable local verification while keeping CI runnable. Two fixture paths exist: - `fixtures/excel/` (tracked): **canonical Excel-generated files** used in CI. - `fixtures/excel_xls/` (tracked): **canonical .xls fixtures** for legacy format testing. +- `fixtures/excel/tier4/` (tracked): **openpyxl-structural Tier 4 fixtures** (sheet + protection, page setup, chart anchoring). Generated by + `scripts/build_tier4_fixtures.py`; expectations are verifier-grade openpyxl + readbacks, marked `generator: openpyxl-structural` in the manifest notes. +- `fixtures/mutation/` (tracked): corporate-model template + mutation manifest for + the template-mutation lane (`scripts/build_mutation_template.py`). +- `fixtures/calc/` (tracked): **cache-free** formula fixture plus LibreOffice-oracle + expected values (`scripts/build_calc_fixture.py`). The fixture must never ship + cached formula values; the builder asserts this and fails loudly. - `test_files/` (gitignored): local scratch output for development. Generate canonical fixtures with: @@ -46,10 +55,13 @@ Features are organized into tiers reflecting complexity: | **Tier 1** (Formatting) | alignment, background_colors, borders, dimensions, number_formats, text_formatting | 6 | | **Tier 2** (Advanced) | comments, conditional_formatting, data_validation, freeze_panes, hyperlinks, images, merged_cells, pivot_tables | 8 | | **Tier 3** (Workbook Metadata) | named_ranges, tables | 2 | +| **Tier 4** (Production surfaces, 2026-09-08) | chart_anchor, page_setup, sheet_protection | 3 | -**Framework coverage:** 19 modeled features total. -**Fresh release snapshot:** 19 tested features, where 18 are scoreable per-library in -the 2026-04-29 wheel-backed WolfXL 2.0 rerun (pivot_tables is tested but N/A across adapters on macOS fixtures). +**Framework coverage:** 22 modeled features total. +**2026-04-29 release snapshot:** 19 tested features, 18 scoreable (pivot_tables N/A on macOS fixtures). +**2026-09-08 competitor snapshot:** all 22 features scored; Tier 4 fixtures are +openpyxl-structural (see Fixtures Policy), so Tier 4 expectations encode openpyxl +semantics, not Excel-authored ground truth. ## Scoring @@ -81,3 +93,33 @@ uv run excelbench report --input results/xlsx/results.json --output results/xlsx - **Secondary tables** can include cross-language libraries such as Apache POI, ClosedXML, Excelize, and ExcelJS. - Cross-language results should be labeled as ecosystem context unless the report is explicitly cross-language-focused. - The current rollout plan for the first two cross-language candidates lives in `docs/trackers/apache-poi-excelize-rollout-plan.md`. + +## Mutation Lane + +`excelbench mutation` measures surgical template editing: each engine changes two +cells in `fixtures/mutation/template_corporate_model.xlsx` in an isolated +subprocess and saves the result. + +- **Wall time**: median over `--repeats` (default 3) subprocess runs. +- **Peak RSS**: median subprocess peak resident set size. +- **Preservation score**: fraction of original package parts retained after the + edit, minus damage penalties; outputs must reopen cleanly with the openpyxl + verifier or the engine is marked `integrity-failed` with score 0. + +Preservation is a structural proxy (ZIP part inventory), not a semantic +equivalence claim. Cite wall time and preservation together. + +## Calculation Lane + +`excelbench calc` measures formula recalculation against +`fixtures/calc/expected_values.json` (133 formula cells, LibreOffice headless +oracle, oracle version pinned in the artifact). + +- The fixture ships **no cached formula values**; an engine only scores by + producing values itself. Cache passthrough cannot score (DEC-026). +- Status semantics are strict: `passed` requires a full match against the + oracle; any wrong or missing value reports `failed` with matched/total and + per-cell mismatch details. +- Formulas avoid `IFS` and `XLOOKUP` because the LibreOffice oracle build + returns `#NAME?` for them on this path; nested `IF` and INDEX/MATCH are used + instead. This constrains function coverage and is documented per artifact. diff --git a/README.md b/README.md index 880baca..11cb22d 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,27 @@ Most Excel library comparisons focus on speed. ExcelBench focuses on the questio > Can this library handle my real spreadsheet without breaking the parts I care about? -ExcelBench models 19 XLSX features across 12+ Python adapters. In the fresh -wheel-backed WolfXL 2.0 release snapshot, 18 are scoreable across libraries -(pivot tables remain N/A on macOS fixtures). +ExcelBench models 22 XLSX features across 14 Python adapters plus a +cross-language context lane (Apache POI, Excelize, zavora-xlsx). Tier 4 +(sheet protection, page setup, chart anchoring) was added in the +2026-09-08 competitor snapshot. ## Results at a Glance +> Competitor snapshot: 2026-09-08 | WolfXL 2.1.0 wheel | aspose-cells-foss 26.7 | [Fidelity](results-2026-09-08/xlsx/README.md) | [Mutation](results-2026-09-08/mutation/README.md) | [Calc](results-2026-09-08/calc/README.md) | [Zavora cross-language](results-2026-09-08/cross-language/README.md) +> +> In that snapshot: openpyxl 22/22, WolfXL 19/22, aspose-cells-foss 11/22 +> green features (WolfXL 2.1.0 gaps: conditional-formatting read, +> named-range and print-title writes). +> +> Mutation suite (two-cell edit on a corporate template): WolfXL patches in +> 1.5s with 100% preservation; openpyxl and aspose rewrite at 60%; +> zavora-xlsx 0.1.2 corrupts package relationships (0%). +> +> Calc tier (133-formula financial DAG, cache-free fixture, LibreOffice +> oracle): LibreOffice 133/133, WolfXL 55/133, aspose-cells-foss 25/133, +> zavora 0/133. +> > Python release snapshot: 2026-04-29 UTC | wheel-backed WolfXL 2.0 rerun | [Fidelity](results-release-2026-04-28/README.md) | [Perf](results-release-2026-04-28/perf/README.md) | [Dashboard](results-release-2026-04-28/DASHBOARD.md) > > In that snapshot, WolfXL reaches `18/18` green features with `100%` pass rate. @@ -21,7 +36,7 @@ wheel-backed WolfXL 2.0 release snapshot, 18 are scoreable across libraries > Pivot capability lane: [separate artifact](results-cross-language-pivots/README.md) because the shipped macOS pivot fixture is not scoreable, while `excelize` can still emit pivot-bearing workbooks. > > Historical public baseline: 2026-02-17 | Excel 16.105.3 | macOS (Apple Silicon) | [Full results](results/xlsx/README.md) - +> > Newer performance snapshot: 2026-04-20 | [Perf results](results/perf/README.md) > > Read [Public Reporting Status](docs/public-reporting.md) before quoting numbers across snapshots. @@ -38,28 +53,36 @@ Cross-language libraries matter too, but for a different reason: they show how s - `Apache POI` - `Excelize` +- `zavora-xlsx` (Rust writer, added 2026-09-08) Pivot tables sit in a separate capability lane. On macOS, the shipped pivot fixture does not currently contain scoreable pivot OOXML, so the pivot story is tracked as a dedicated artifact instead of being mixed into the scored lane. See [cross-language comparison strategy](docs/trackers/cross-language-comparison-strategy.md). -## Three Lanes +## Lanes 1. **Python replacement lane** Use this when the question is: what should a Python team use instead of `openpyxl`? 2. **Cross-language context lane** -Use this when the question is: how does WolfXL compare to serious spreadsheet tooling in Java and Go? +Use this when the question is: how does WolfXL compare to serious spreadsheet tooling in Java, Go, and Rust? 3. **Pivot capability lane** Use this when the question is: can the cross-language helpers detect or emit pivot-bearing workbooks even when the main scored fixture is not valid on macOS? +4. **Template-mutation lane** +Use this when the question is: which engine can surgically edit a corporate template fastest while preserving the package? + +5. **Formula-recalculation lane** +Use this when the question is: which engine actually computes a 133-formula financial DAG from scratch (cache-free fixture, LibreOffice oracle)? + ### Library Comparison | Library | Caps | Fidelity | Read Speed | Write Speed | Modify | |---------|:----:|:--------:|:----------:|:-----------:|:------:| -| **wolfxl** | R+W | 18/18 in 2026-04-29 release snapshot | workload-specific | workload-specific | Patch | -| openpyxl | R+W | 18/18 in 2026-04-29 release snapshot | 1x (baseline per workload) | 1x (baseline per workload) | Rewrite | +| **wolfxl** | R+W | 19/22 in 2026-09-08 competitor snapshot (18/18 in 2026-04-29 snapshot) | workload-specific | workload-specific | Patch (100% preservation in mutation suite) | +| openpyxl | R+W | 22/22 in 2026-09-08 competitor snapshot | 1x (baseline per workload) | 1x (baseline per workload) | Rewrite (60% preservation in mutation suite) | +| aspose-cells-foss | R+W | 11/22 in 2026-09-08 competitor snapshot | workload-specific | workload-specific | Rewrite (60% preservation) | | xlsxwriter | W | 15/18 in 2026-04-29 release snapshot | -- | ~1x | No | | xlsxwriter-constmem | W | 12/18 in 2026-04-29 release snapshot | -- | ~2x | No | | python-calamine | R | 1/18 in 2026-04-29 release snapshot | ~1.3x | -- | No | @@ -69,13 +92,15 @@ Use this when the question is: can the cross-language helpers detect or emit piv > Speed numbers are snapshot-specific. Always cite the artifact date, workload, and profile. See [performance results](results/perf/README.md), [METHODOLOGY.md](METHODOLOGY.md), and [Public Reporting Status](docs/public-reporting.md). ### Key Findings - -- **High-fidelity libraries are rare**: in the fresh wheel-backed release snapshot, only openpyxl and WolfXL reach 18/18 green features -- **Patch modify is structurally different**: WolfXL's `load_workbook(path, modify=True)` uses surgical ZIP patching rather than a full workbook rewrite +- **High-fidelity libraries are rare**: in the 2026-04-29 release snapshot, only openpyxl and WolfXL reached 18/18 green features; in the 2026-09-08 competitor snapshot (22 features), openpyxl holds 22/22 while WolfXL 2.1.0 drops to 19/22 +- **WolfXL 2.1.0 regression signal**: conditional-formatting read scores 0 and named-range / print-title writes score 2 in the 2026-09-08 snapshot; tracked for the WolfXL repo +- **Patch modify is structurally different**: WolfXL's `load_workbook(path, modify=True)` uses surgical ZIP patching; it is the only engine reaching 100% package preservation in the mutation suite - **The abstraction tax is real**: pandas wraps openpyxl but drops from 16 to 3 green features due to DataFrame coercion (errors become NaN) - **Speed vs fidelity tradeoff is measurable**: use the perf snapshot together with the fidelity matrix rather than quoting one without the other - **Optimization modes have clear costs**: openpyxl-readonly loses 13 green features for streaming speed -- **Cross-language context is now strong too**: both `Apache POI` and `Excelize` land at `18/18` in the current scored write lane +- **Cross-language context is now strong too**: `Apache POI` and `Excelize` land at `18/18` in the scored write lane; `zavora-xlsx` 0.1.2 writes fast but corrupts hyperlink relationships on mutate and cannot recalculate +- **Calculation is a differentiator**: only LibreOffice computes the full 133-formula DAG; WolfXL 2.1.0 covers 55/133 (power-operator family returns None), aspose-cells-foss 25/133 + See the [release snapshot dashboard](results-release-2026-04-28/DASHBOARD.md) for the fresh wheel-backed combined view, or the [historical dashboard](results/DASHBOARD.md) for the older public baseline. @@ -90,11 +115,13 @@ See the [release snapshot dashboard](results-release-2026-04-28/DASHBOARD.md) fo ## Libraries Tested -### XLSX Profile (12 adapters) +### XLSX Profile (14 adapters) | Library | Version | Lang | Caps | Green Features | |:--------|:--------|:-----|:-----|:--------------:| -| [openpyxl](https://openpyxl.readthedocs.io/) | 3.1.5 | Python | R+W | 18/18 | +| [WolfXL](https://github.com/SynthGL/wolfxl) | 2.1.0 | Python (Rust core) | R+W | 19/22 (2026-09-08 snapshot) | +| [openpyxl](https://openpyxl.readthedocs.io/) | 3.1.5 | Python | R+W | 22/22 (2026-09-08 snapshot) | +| [aspose-cells-foss](https://pypi.org/project/aspose-cells-foss/) | 26.7 | Python (JVM-core FOSS) | R+W | 11/22 (2026-09-08 snapshot) | | [XlsxWriter](https://xlsxwriter.readthedocs.io/) | 3.2.9 | Python | W | 15/18 | | [xlsxwriter-constmem](https://xlsxwriter.readthedocs.io/) | 3.2.9 | Python | W | 12/18 | | [openpyxl-readonly](https://openpyxl.readthedocs.io/) | 3.1.5 | Python | R | 3/18 | @@ -107,6 +134,18 @@ See the [release snapshot dashboard](results-release-2026-04-28/DASHBOARD.md) fo | [xlwt](https://github.com/python-excel/xlwt) | 1.3.0 | Python | W | 4/18 | | [xlrd](https://github.com/python-excel/xlrd) | 2.0.2 | Python | R | .xls only | +> Green-feature counts are per dated snapshot; `x/18` numbers come from the +> 2026-04-29 release snapshot and `x/22` from the 2026-09-08 competitor +> snapshot (Tier 4 added). Never mix counts across snapshots. + +### Cross-Language Context (oracle helpers) + +| Library | Version | Lang | Caps | Notes | +|:--------|:--------|:-----|:-----|:------| +| Apache POI | 5.x | Java | W | 18/18 scored write lane (2026-04-29) | +| Excelize | 2.x | Go | W | 18/18 scored write lane (2026-04-29) | +| zavora-xlsx | 0.1.2 | Rust | W | Fast writer; 0.1.2 corrupts hyperlink relationships on mutate; no recalc | + ### XLS Profile (2 adapters) | Library | Green Features | Notes | @@ -143,6 +182,7 @@ ExcelBench now ships a separate cross-language context snapshot for mature non-P - `Apache POI` (Java) - `Excelize` (Go) +- `zavora-xlsx` (Rust writer, added 2026-09-08; helper in `tools/external-oracles/zavora`) These are not framed as Python drop-in replacements. They answer a different question: how strong is WolfXL relative to serious spreadsheet tooling outside Python? @@ -214,6 +254,12 @@ uv sync # Run the benchmark against pre-built fixtures (no Excel required) uv run excelbench benchmark --tests fixtures/excel --output results +# Template-mutation suite (wall time, RSS, preservation) +uv run excelbench mutation + +# Formula-recalculation tier (cache-free fixture, LibreOffice oracle) +uv run excelbench calc + # Generate the heatmap uv run excelbench heatmap @@ -232,7 +278,7 @@ uv run excelbench generate --output fixtures/excel ## Feature Coverage -### Tested (19 features; 18 currently scoreable in the release snapshot) +### Tested (22 features) | Tier | Features | Count | |:-----|:---------|:-----:| @@ -240,16 +286,21 @@ uv run excelbench generate --output fixtures/excel | **Tier 1** -- Formatting | Text formatting, background colors, number formats, alignment, borders, dimensions | 6 | | **Tier 2** -- Advanced | Merged cells, conditional formatting, data validation, hyperlinks, images, comments, freeze panes, pivot tables | 8 | | **Tier 3** -- Workbook metadata | Named ranges, tables | 2 | +| **Tier 4** -- Production surfaces (2026-09-08) | Sheet protection, page setup, chart anchoring | 3 | > Pivot tables are tested but score N/A across all adapters in the current macOS run. -> Library green-feature scores therefore use an /18 denominator in the fresh release snapshot. +> Green-feature denominators: /18 in the 2026-04-29 release snapshot, /22 in the 2026-09-08 competitor snapshot. ### Planned -Charts, print settings, protection. +None currently queued. Tier 4 (charts anchoring, print settings, protection) shipped 2026-09-08. ## Detailed Results +- **[Competitor snapshot fidelity](results-2026-09-08/xlsx/README.md)** -- 22 features x 14 Python adapters, WolfXL 2.1.0 + aspose-cells-foss +- **[Competitor snapshot mutation](results-2026-09-08/mutation/README.md)** -- template mutation: wall time, RSS, preservation +- **[Competitor snapshot calc](results-2026-09-08/calc/README.md)** -- 133-formula financial DAG vs LibreOffice oracle +- **[Competitor snapshot zavora cross-language](results-2026-09-08/cross-language/README.md)** -- zavora-xlsx 0.1.2 Rust writer context - **[XLSX results](results/xlsx/README.md)** -- per-library, per-test-case breakdowns with tier list - **[Release snapshot results](results-release-2026-04-28/README.md)** -- fresh wheel-backed WolfXL 2.0 rerun - **[XLS results](results/xls/README.md)** -- legacy format results diff --git a/TRACKER.md b/TRACKER.md index 7f432d5..5615c73 100644 --- a/TRACKER.md +++ b/TRACKER.md @@ -4,7 +4,7 @@ > self-contained sprint (one branch, one PR, one row flip). Resume cold by reading this file > and the most recent `[*INCOMPLETE*]` marker. -**Last updated**: 2026-04-27 (S3 shipped) +**Last updated**: 2026-09-08 (competitor snapshot landed; S4+ perf sprints still queued) ## Status Table @@ -17,6 +17,7 @@ | S5 | Workbook complexity perf | Planned | M (1 wk) | `feat/perf-complexity` | — | — | | S6 | Cold-start / warm path | Planned | S (3–5 d) | `feat/perf-cold-start` | — | — | | S7 | Round-trip fidelity (LibreOffice) | Planned | L (~2 wk) | `feat/fidelity-roundtrip` | — | — | +| C1 | Competitor snapshot: aspose-foss + zavora adapters, Tier 4, mutation + calc lanes | Shipped (branch) | L | `feat/competitor-snapshot-2026-09` | — | this branch | **Status legend**: `Planned` → `In Progress` → `Shipped` (or `Blocked` with reason). @@ -182,3 +183,26 @@ Use this template when appending to **Acceptance Notes** below. - Decisions: [`decisions.md`](decisions.md) - Key seams: `src/excelbench/perf/runner.py`, `src/excelbench/harness/adapters/base.py`, `src/excelbench/results/html_dashboard.py`. + +## Session Log: Competitor Snapshot (2026-09-08) + +Branch `feat/competitor-snapshot-2026-09` (this branch). + +**Shipped**: +- `aspose-cells-foss` adapter (Python lane, `aspose` extra) — 11/22 green. +- `zavora-xlsx` external oracle adapter (cross-language lane) + Rust helper in + `tools/external-oracles/zavora`. +- Tier 4 features: sheet_protection, page_setup, chart_anchor (22 scored + features), openpyxl-structural fixtures. +- wolfxl adapter ported to WolfXL 2.1.0 public API (19/22; CF read 0, + named-range/print-title writes 2). +- Template-mutation lane (`excelbench mutation`): wolfxl 100% preservation; + openpyxl/aspose 60%; zavora 0.1.2 integrity-failed. +- Calc tier (`excelbench calc`): cache-free 133-formula fixture, LibreOffice + oracle; LO 133/133, wolfxl 55/133 (power-operator family returns None), + aspose 25/133, zavora 0/133. +- Snapshot artifacts: `results-2026-09-08/{xlsx,mutation,calc,cross-language}`. +- Decisions DEC-023..DEC-026. + +**Verification**: full pytest suite + ruff on this branch (see PR body for +exact receipts). diff --git a/architecture.md b/architecture.md index 82b9d95..c270295 100644 --- a/architecture.md +++ b/architecture.md @@ -76,15 +76,23 @@ Most-touched top-level directories: - `harness/roundtrip_runner.py`: open/save idempotence context lane - `harness/compat_cases.py`: openpyxl-style compatibility snippet lane - `harness/artifact_context.py`: chart and macro package evidence lanes + - `harness/mutation.py`: template-mutation lane (subprocess wall time, RSS, + package-preservation scoring) + - `harness/calc.py`: formula-recalculation tier engines (wolfxl, LibreOffice, + aspose-cells-foss, zavora oracle) against the cache-free fixture + - `modifiable.py`: engine registry for mutation-capable adapters - `harness/external_fixture_specs/`: tool-specific external oracle fixture definitions imported by the fixture-pack generator - `perf/`: performance runner + renderer - `results/`: fidelity result renderers (md/csv) + dashboards/plots - `fixtures/` - - `excel/`: canonical .xlsx fixtures (git-tracked, Excel-generated) + - `excel/`: canonical .xlsx fixtures (git-tracked; tiers 0-3 Excel-generated, + `excel/tier4/` openpyxl-structural) - `excel_xls/`: canonical .xls fixtures - `throughput_xlsx/`: scale fixtures for perf/throughput workloads + - `mutation/`: corporate-model template + mutation manifest + - `calc/`: cache-free formula fixture + LibreOffice oracle expected values - `tools/external-oracles/` - Optional subprocess helpers for non-Python oracle tools. @@ -100,6 +108,8 @@ Most-touched top-level directories: merges, freeze panes, and sheet protection. - `closedxml/`: .NET helper that generates workbooks with ClosedXML tables, pivots, and conditional formatting. + - `zavora/`: Rust helper (zavora-xlsx) for write/mutate/calculate oracle + operations over the stdin/stdout JSON contract. - `npoi/`: .NET helper that generates POI-style workbooks with NPOI formulas, comments, rich text, merged ranges, and sheet protection. diff --git a/decisions.md b/decisions.md index c74dc0d..f8ffe66 100644 --- a/decisions.md +++ b/decisions.md @@ -40,6 +40,141 @@ Skip logging for routine bug fixes, refactors, or incremental test additions. ## Decisions +### DEC-023 — Tier-4 fidelity features via openpyxl-structural fixtures (2026-09-08) + +**Context**: The scored matrix stopped at 19 features. Sheet protection, page +setup, and chart anchoring are recurring production surfaces with no +cross-library comparison, and this workstation has no Excel app to author +authoritative fixtures. + +**Decision**: + +- Add three Tier-4 features: `sheet_protection`, `page_setup`, + `chart_anchor` (22 scored features total). +- Fixtures are built by `scripts/build_tier4_fixtures.py` with openpyxl and + marked `generator: openpyxl-structural` in the manifest notes; expected + values are full adapter readbacks from the verifier-grade openpyxl + implementation, not Excel screenshots. +- Raw OOXML semantics are pinned in `adapters/base.py` optional methods + (protection attribute True = BLOCKED; `fit_to_height=None` when only + `fit_to_width` is set; chart anchors are two-cell `from`/`to` only). +- Write-only keys that no reader can verify (`password`, + `data_ref`/`categories_ref`) ride in the manifest and are stripped before + comparison, following the `_strip_cf_priority` precedent. + +**Alternatives considered**: + +1. Excel-authored fixtures - unavailable on this machine; would also block + CI reproduction. +2. Skip the features until Excel access exists - rejected; the features are + structural and openpyxl is the de-facto Python semantic reference. + +**Consequences**: + +- Tier-4 expectations encode openpyxl's semantics, not Excel's. Any future + Excel-authored evidence that disagrees becomes a documented fixture + revision, not a silent change. +- Most read-optimized adapters score 0 on Tier-4 by design (structured + unsupported failures), which is the correct public signal. + +### DEC-024 — Competitor adapters: aspose-cells-foss (Python lane) and zavora-xlsx (cross-language) (2026-09-08) + +**Context**: The public matrix lacked two comparison points users ask for: +Aspose's FOSS Python offering and a fast Rust writer (zavora-xlsx). + +**Decision**: + +- `aspose-cells-foss` joins the Python lane behind the `aspose` extra + (`aspose-cells-foss>=26.7`), availability-gated so installs without the + extra lose nothing. +- `zavora-xlsx` joins the cross-language lane only + (`CROSS_LANGUAGE_ADAPTER_NAMES`) via the DEC-021 external-oracle subprocess + contract; a Rust helper lives in `tools/external-oracles/zavora`. +- Both adapters raise structured `UnsupportedAdapterOperationError` for + unsupported operations; no silent passes. + +**Alternatives considered**: + +1. Put zavora in the Python lane - rejected; it is not a Python library and + would blur the Python-first decision surface. +2. Skip aspose FOSS due to missing pivots/chart rendering - rejected; its + 11/22 with explicit gaps is exactly the comparison signal the matrix needs. + +**Consequences**: + +- The Python lane grows to 14 adapters; the main snapshot stays Python-only. +- Upstream zavora-xlsx 0.1.2 defects (hyperlink relationship corruption on + mutate/save, `recalculate()` returning null caches) become visible, scored + findings rather than hidden skips. + +### DEC-025 — Template-mutation suite: wall time, RSS, preservation score (2026-09-08) + +**Context**: Modify workloads were only measurable via WolfXL's patch path in +perf lanes. Real corporate deliverables are mutated templates: change two +cells, save, keep everything else comparable. + +**Decision**: + +- Add `excelbench mutation` running surgical two-cell mutations on + `fixtures/mutation/template_corporate_model.xlsx` (built by + `scripts/build_mutation_template.py`; styles, CF, named ranges, hyperlinks, + data validation, multiple sheets). +- Score three axes per engine: median wall time over repeats, peak RSS, and a + package-preservation score (retained parts minus damage penalties). +- Engines: openpyxl, wolfxl (`modify=True`), aspose-cells-foss, zavora-xlsx + oracle mutate. Integrity failure (output cannot be reopened by the + verifier) scores 0 and is labeled `integrity-failed`, not silently skipped. + +**Alternatives considered**: + +1. Fold into perf lanes - rejected; perf lanes are cell-throughput oriented + and have no preservation axis. +2. Byte-identical diff as the score - rejected; ZIP timestamps make byte + equality meaningless. Structural part retention is the honest proxy. + +**Consequences**: + +- Preservation is a structural proxy, not a semantic one. The verifier + reopens outputs with openpyxl to catch the failure class that matters + (corrupt relationships, as zavora 0.1.2 demonstrates). + +### DEC-026 — Calc tier: cache-free fixture, LibreOffice oracle, strict status semantics (2026-09-08) + +**Context**: Formula recalculation had no lane. The first builder draft +shipped LibreOffice-computed caches inside the fixture itself, which let +cache-passthrough engines score a perfect 133/133 without calculating +anything (zavora 0.1.2 preserves input caches on save). + +**Decision**: + +- The canonical fixture `fixtures/calc/financial_model.xlsx` ships formulas + with NO cached values; the builder asserts cache-freedom and fails loudly + otherwise. +- Oracle values are harvested from a throwaway LibreOffice headless + recalculation copy (`expected_values.json`, 133 cells, oracle version + pinned). +- An engine that runs but scores below the oracle total reports `failed` + with matched/total; only a full match is `passed`. Missing-value + mismatches are counted separately from wrong-value mismatches. +- Nested `IF` is used instead of `IFS` (LibreOffice returns `#NAME?` on this + path); XLOOKUP is omitted for the same reason. + +**Alternatives considered**: + +1. Keep cached fixture and accept passthrough - rejected; it scores + file-copying, not calculation. +2. Excel as oracle - unavailable on this machine. + +**Consequences**: + +- Honest first snapshot: LibreOffice 133/133; wolfxl 55/133 (its calculator + returns None for the `^` power-operator formula family and dependents); + aspose-cells-foss 25/133 (FOSS FormulaEvaluator has no value for 107 + formulas); zavora 0.1.2 0/133 (writes no caches). +- Cache-free fixtures make engines without write-back caches look strictly + worse; that is the intended signal, documented here. + + ### DEC-022 — Semantic diff and context lanes stay additive (2026-04-29) **Context**: ExcelBench needed better evidence for workbook drift, roundtrip diff --git a/docs/public-reporting.md b/docs/public-reporting.md index d44a6ff..3c080a6 100644 --- a/docs/public-reporting.md +++ b/docs/public-reporting.md @@ -31,6 +31,10 @@ This page explains what the current ExcelBench repo artifacts mean and how to ci | `results-release-2026-04-28/perf/README.md` | 2026-04-29 | Matching wheel-backed performance rerun | | `results-cross-language/README.md` | 2026-04-29 | Checked-in cross-language context snapshot for Apache POI and Excelize | | `results-cross-language-pivots/README.md` | 2026-04-29 | Separate pivot capability artifact for cross-language helpers | +| `results-2026-09-08/xlsx/README.md` | 2026-09-08 | Competitor fidelity snapshot: 22 features, 14 Python adapters, WolfXL 2.1.0 + aspose-cells-foss | +| `results-2026-09-08/mutation/README.md` | 2026-09-08 | Template-mutation lane (wall time, RSS, preservation) | +| `results-2026-09-08/calc/README.md` | 2026-09-08 | Formula-recalculation tier vs LibreOffice oracle on a cache-free fixture | +| `results-2026-09-08/cross-language/README.md` | 2026-09-08 | zavora-xlsx 0.1.2 Rust writer cross-language context | ## Safe Claims Right Now @@ -40,6 +44,8 @@ This page explains what the current ExcelBench repo artifacts mean and how to ci - The fresh WolfXL 2.0 wheel-backed release snapshot is available separately from the older historical baseline. - A separate cross-language context snapshot is available for ecosystem positioning and should be cited as a separate lane from the Python hero table. - A separate pivot capability artifact is available for cross-language helpers and should be cited as a capability note, not as a scored lane. +- The 2026-09-08 competitor snapshot extends the scored matrix to 22 features (Tier 4 is openpyxl-structural, not Excel-authored) and adds aspose-cells-foss; its fidelity numbers must not be mixed with /18 denominators from earlier snapshots. +- The mutation and calc lanes are separate decision surfaces (modify-integrity and calculation correctness) and must be cited as their own artifacts, never folded into feature-parity claims. ## Claims That Need Fresh Reruns diff --git a/fixtures/calc/expected_values.json b/fixtures/calc/expected_values.json new file mode 100644 index 0000000..3daf8de --- /dev/null +++ b/fixtures/calc/expected_values.json @@ -0,0 +1,537 @@ +{ + "cells": { + "Schedule!B10": { + "type": "number", + "value": 0.0 + }, + "Schedule!B11": { + "type": "number", + "value": -308872.0 + }, + "Schedule!B2": { + "type": "number", + "value": 100000.0 + }, + "Schedule!B3": { + "type": "number", + "value": 38000.0 + }, + "Schedule!B4": { + "type": "number", + "value": 62000.0 + }, + "Schedule!B5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!B6": { + "type": "number", + "value": 488.0 + }, + "Schedule!B7": { + "type": "number", + "value": 719.0 + }, + "Schedule!B8": { + "type": "number", + "value": 400872.0 + }, + "Schedule!B9": { + "type": "number", + "value": -300872.0 + }, + "Schedule!C10": { + "type": "number", + "value": 0.0 + }, + "Schedule!C11": { + "type": "number", + "value": -306442.0 + }, + "Schedule!C2": { + "type": "number", + "value": 104500.0 + }, + "Schedule!C3": { + "type": "number", + "value": 39710.0 + }, + "Schedule!C4": { + "type": "number", + "value": 64790.0 + }, + "Schedule!C5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!C6": { + "type": "number", + "value": 488.0 + }, + "Schedule!C7": { + "type": "number", + "value": 719.0 + }, + "Schedule!C8": { + "type": "number", + "value": 402582.0 + }, + "Schedule!C9": { + "type": "number", + "value": -298082.0 + }, + "Schedule!D10": { + "type": "number", + "value": 0.0 + }, + "Schedule!D11": { + "type": "number", + "value": -303902.65 + }, + "Schedule!D2": { + "type": "number", + "value": 109202.5 + }, + "Schedule!D3": { + "type": "number", + "value": 41496.95 + }, + "Schedule!D4": { + "type": "number", + "value": 67705.55 + }, + "Schedule!D5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!D6": { + "type": "number", + "value": 488.0 + }, + "Schedule!D7": { + "type": "number", + "value": 719.0 + }, + "Schedule!D8": { + "type": "number", + "value": 404368.95 + }, + "Schedule!D9": { + "type": "number", + "value": -295166.45 + }, + "Schedule!E10": { + "type": "number", + "value": 0.0 + }, + "Schedule!E11": { + "type": "number", + "value": -301249.02925 + }, + "Schedule!E2": { + "type": "number", + "value": 114116.6125 + }, + "Schedule!E3": { + "type": "number", + "value": 43364.31275 + }, + "Schedule!E4": { + "type": "number", + "value": 70752.29975 + }, + "Schedule!E5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!E6": { + "type": "number", + "value": 488.0 + }, + "Schedule!E7": { + "type": "number", + "value": 719.0 + }, + "Schedule!E8": { + "type": "number", + "value": 406236.31275 + }, + "Schedule!E9": { + "type": "number", + "value": -292119.70025 + }, + "Schedule!F10": { + "type": "number", + "value": 0.0 + }, + "Schedule!F11": { + "type": "number", + "value": -298475.99556625 + }, + "Schedule!F2": { + "type": "number", + "value": 119251.8600625 + }, + "Schedule!F3": { + "type": "number", + "value": 45315.70682375 + }, + "Schedule!F4": { + "type": "number", + "value": 73936.15323875 + }, + "Schedule!F5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!F6": { + "type": "number", + "value": 488.0 + }, + "Schedule!F7": { + "type": "number", + "value": 719.0 + }, + "Schedule!F8": { + "type": "number", + "value": 408187.70682375 + }, + "Schedule!F9": { + "type": "number", + "value": -288935.84676125 + }, + "Schedule!G10": { + "type": "number", + "value": 0.0 + }, + "Schedule!G11": { + "type": "number", + "value": -295578.175366731 + }, + "Schedule!G2": { + "type": "number", + "value": 124618.193765312 + }, + "Schedule!G3": { + "type": "number", + "value": 47354.9136308187 + }, + "Schedule!G4": { + "type": "number", + "value": 77263.2801344937 + }, + "Schedule!G5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!G6": { + "type": "number", + "value": 488.0 + }, + "Schedule!G7": { + "type": "number", + "value": 719.0 + }, + "Schedule!G8": { + "type": "number", + "value": 410226.913630819 + }, + "Schedule!G9": { + "type": "number", + "value": -285608.719865506 + }, + "Schedule!H10": { + "type": "number", + "value": 0.0 + }, + "Schedule!H11": { + "type": "number", + "value": -292549.953258234 + }, + "Schedule!H2": { + "type": "number", + "value": 130226.012484752 + }, + "Schedule!H3": { + "type": "number", + "value": 49485.8847442056 + }, + "Schedule!H4": { + "type": "number", + "value": 80740.127740546 + }, + "Schedule!H5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!H6": { + "type": "number", + "value": 488.0 + }, + "Schedule!H7": { + "type": "number", + "value": 719.0 + }, + "Schedule!H8": { + "type": "number", + "value": 412357.884744206 + }, + "Schedule!H9": { + "type": "number", + "value": -282131.872259454 + }, + "Schedule!I10": { + "type": "number", + "value": 0.0 + }, + "Schedule!I11": { + "type": "number", + "value": -289385.461154855 + }, + "Schedule!I2": { + "type": "number", + "value": 136086.183046565 + }, + "Schedule!I3": { + "type": "number", + "value": 51712.7495576948 + }, + "Schedule!I4": { + "type": "number", + "value": 84373.4334888705 + }, + "Schedule!I5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!I6": { + "type": "number", + "value": 488.0 + }, + "Schedule!I7": { + "type": "number", + "value": 719.0 + }, + "Schedule!I8": { + "type": "number", + "value": 414584.749557695 + }, + "Schedule!I9": { + "type": "number", + "value": -278498.56651113 + }, + "Schedule!J10": { + "type": "number", + "value": 0.0 + }, + "Schedule!J11": { + "type": "number", + "value": -286078.566906823 + }, + "Schedule!J2": { + "type": "number", + "value": 142210.061283661 + }, + "Schedule!J3": { + "type": "number", + "value": 54039.8232877911 + }, + "Schedule!J4": { + "type": "number", + "value": 88170.2379958697 + }, + "Schedule!J5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!J6": { + "type": "number", + "value": 488.0 + }, + "Schedule!J7": { + "type": "number", + "value": 719.0 + }, + "Schedule!J8": { + "type": "number", + "value": 416911.823287791 + }, + "Schedule!J9": { + "type": "number", + "value": -274701.76200413 + }, + "Schedule!K10": { + "type": "number", + "value": 0.0 + }, + "Schedule!K11": { + "type": "number", + "value": -282622.86241763 + }, + "Schedule!K2": { + "type": "number", + "value": 148609.514041425 + }, + "Schedule!K3": { + "type": "number", + "value": 56471.6153357417 + }, + "Schedule!K4": { + "type": "number", + "value": 92137.8987056838 + }, + "Schedule!K5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!K6": { + "type": "number", + "value": 488.0 + }, + "Schedule!K7": { + "type": "number", + "value": 719.0 + }, + "Schedule!K8": { + "type": "number", + "value": 419343.615335742 + }, + "Schedule!K9": { + "type": "number", + "value": -270734.101294316 + }, + "Schedule!L10": { + "type": "number", + "value": 0.0 + }, + "Schedule!L11": { + "type": "number", + "value": -279011.651226424 + }, + "Schedule!L2": { + "type": "number", + "value": 155296.94217329 + }, + "Schedule!L3": { + "type": "number", + "value": 59012.8380258501 + }, + "Schedule!L4": { + "type": "number", + "value": 96284.1041474396 + }, + "Schedule!L5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!L6": { + "type": "number", + "value": 488.0 + }, + "Schedule!L7": { + "type": "number", + "value": 719.0 + }, + "Schedule!L8": { + "type": "number", + "value": 421884.83802585 + }, + "Schedule!L9": { + "type": "number", + "value": -266587.89585256 + }, + "Schedule!M10": { + "type": "number", + "value": 0.0 + }, + "Schedule!M11": { + "type": "number", + "value": -275237.935531613 + }, + "Schedule!M2": { + "type": "number", + "value": 162285.304571088 + }, + "Schedule!M3": { + "type": "number", + "value": 61668.4157370133 + }, + "Schedule!M4": { + "type": "number", + "value": 100616.888834074 + }, + "Schedule!M5": { + "type": "number", + "value": 12000.0 + }, + "Schedule!M6": { + "type": "number", + "value": 488.0 + }, + "Schedule!M7": { + "type": "number", + "value": 719.0 + }, + "Schedule!M8": { + "type": "number", + "value": 424540.415737013 + }, + "Schedule!M9": { + "type": "number", + "value": -262255.111165926 + }, + "Summary!B10": { + "type": "number", + "value": -2021215.15613594 + }, + "Summary!B11": { + "type": "number", + "value": 0.213327377 + }, + "Summary!B12": { + "type": "number", + "value": 45777.0 + }, + "Summary!B13": { + "type": "number", + "value": 45777.0 + }, + "Summary!B14": { + "type": "number", + "value": 16.0 + }, + "Summary!B15": { + "type": "number", + "value": 4.0 + }, + "Summary!B2": { + "type": "number", + "value": 0.0 + }, + "Summary!B3": { + "type": "number", + "value": 2.0 + }, + "Summary!B4": { + "type": "number", + "value": -300872.0 + }, + "Summary!B5": { + "type": "number", + "value": -262255.111165926 + }, + "Summary!B6": { + "type": "number", + "value": -293283.86 + }, + "Summary!B7": { + "type": "number", + "value": 20.0 + }, + "Summary!B8": { + "type": "number", + "value": 125.25 + } + }, + "oracle": "libreoffice/LibreOffice 26.8.0.3 bce0998afefdbc355585ca324285661a2170ba77" +} diff --git a/fixtures/calc/financial_model.xlsx b/fixtures/calc/financial_model.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..64efb664b5007dfe244eb9b5ee691f59623948cd GIT binary patch literal 9159 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 literal 0 HcmV?d00001 diff --git a/fixtures/excel/manifest.json b/fixtures/excel/manifest.json index 6e19e92..59f0d32 100644 --- a/fixtures/excel/manifest.json +++ b/fixtures/excel/manifest.json @@ -1556,6 +1556,183 @@ "importance": "edge" } ] + }, + { + "path": "tier4/20_sheet_protection.xlsx", + "feature": "sheet_protection", + "tier": 4, + "file_format": "xlsx", + "test_cases": [ + { + "id": "prot_basic", + "label": "Protection: basic (OOXML defaults)", + "row": 2, + "sheet": "sheet_protection_basic", + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "importance": "basic" + }, + { + "id": "prot_password", + "label": "Protection: with password hash", + "row": 2, + "sheet": "sheet_protection_password", + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "importance": "basic" + }, + { + "id": "prot_granular", + "label": "Protection: granular attribute flags", + "row": 2, + "sheet": "sheet_protection_granular", + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "importance": "edge" + } + ] + }, + { + "path": "tier4/21_page_setup.xlsx", + "feature": "page_setup", + "tier": 4, + "file_format": "xlsx", + "test_cases": [ + { + "id": "page_setup_landscape", + "label": "Page setup: landscape + fit-to-width", + "row": 2, + "sheet": "page_setup_landscape", + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "importance": "basic" + }, + { + "id": "page_setup_scale", + "label": "Page setup: portrait at 75% scale", + "row": 2, + "sheet": "page_setup_scale", + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "importance": "basic" + }, + { + "id": "page_setup_titles", + "label": "Page setup: print titles + header/footer", + "row": 2, + "sheet": "page_setup_titles", + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "importance": "edge" + } + ] + }, + { + "path": "tier4/22_chart_anchor.xlsx", + "feature": "chart_anchor", + "tier": 4, + "file_format": "xlsx", + "test_cases": [ + { + "id": "chart_bar", + "label": "Chart: bar with twoCell anchor", + "row": 2, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "importance": "basic" + }, + { + "id": "chart_line", + "label": "Chart: line with twoCell anchor", + "row": 2, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "importance": "edge" + } + ] } - ] -} \ No newline at end of file + ], + "notes": { + "tier4_generator": "openpyxl-structural", + "tier4_generated_at": "2026-09-08T05:26:38.636308+00:00", + "tier4_excel_version": "none" + } +} diff --git a/fixtures/excel/tier4/20_sheet_protection.xlsx b/fixtures/excel/tier4/20_sheet_protection.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..7cbfb7c8e7ac5ed651811a739f6e4fc413467462 GIT binary patch literal 6382 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 Pn6NJ{tg7}B{kZ!dp!D?J literal 0 HcmV?d00001 diff --git a/fixtures/excel/tier4/21_page_setup.xlsx b/fixtures/excel/tier4/21_page_setup.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..837a8635d244983f4a810d06c41bcce41c75f28c GIT binary patch literal 6231 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 Vj0Ec^0|1z?9}Y}axd?yW{Rcy`nM(iw literal 0 HcmV?d00001 diff --git a/fixtures/excel/tier4/22_chart_anchor.xlsx b/fixtures/excel/tier4/22_chart_anchor.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..1e73e3fbcb074556a355ee95b3e91121aebc4582 GIT binary patch literal 7046 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" + }, + "parts": [ + "[Content_Types].xml", + "_rels/.rels", + "customXml/_rels/item1.xml.rels", + "customXml/item1.xml", + "customXml/itemProps1.xml", + "docProps/app.xml", + "docProps/core.xml", + "xl/_rels/workbook.xml.rels", + "xl/charts/chart1.xml", + "xl/charts/chart2.xml", + "xl/comments/comment1.xml", + "xl/drawings/_rels/drawing1.xml.rels", + "xl/drawings/commentsDrawing1.vml", + "xl/drawings/drawing1.xml", + "xl/styles.xml", + "xl/tables/table1.xml", + "xl/theme/theme1.xml", + "xl/workbook.xml", + "xl/worksheets/_rels/sheet1.xml.rels", + "xl/worksheets/_rels/sheet3.xml.rels", + "xl/worksheets/sheet1.xml", + "xl/worksheets/sheet2.xml", + "xl/worksheets/sheet3.xml" + ], + "second_mutation": { + "cell": "C3", + "sheet": "Inputs", + "value": 1337 + } +} diff --git a/fixtures/mutation/template_corporate_model.xlsx b/fixtures/mutation/template_corporate_model.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..91c4bc3f47c84150cb672e75590b6c99b5dc5144 GIT binary patch literal 15043 zcmaKT1wb6jvNrDS!QI`R0KwgY!(zeRHCPDl!6i5ZcXxN!#eycd1P$_Ua_&31hyT0> z%+Aix_03dwbxlpzSITmbP*`AKU~r&~Ob=DnQy~u=49ppHhzUBQD{gP+VrJ)JsP5@t z=B&@`VQbU>R!FIr6>aSfTO|pF){zcFte6S1N(>g}?P4?M+ildlRn#XT^N;Geuf;ye zGCC4&wBPugx{Unrt2{78L@AiAoz@U0ruzJWF5h5WlECm?W8TlZ{vTIs5Y$+uj!AFV zfdT`{>YsV{1_BEcW_bIBY}dlInHPMZZPEJm9isKOR=LhuB9Pu3Y8yxu(;Xvxz3x zA5hwQA<1{8lduoMWIe^P(Z{3BAL?$~nFf>RQpTO^kkNmrOHn`X4pqkc!u;#AJpT7shPeBE*rih2 z&L<64PGDwSqn`_yUrO$iJ*qvDgMTKzRJf%rHvX~Z9g|(#rlaHr@P?cITw24h^l(I-ZFNcy@Kvnz|A`lG9KWocp8c+X~$0sb)b5*QdsKrg-6~-HY_znktm5<{Q6{~VkdpO z%fzk7NC_LpO8Q`g;iq-k9<-&4W%}mO<>WGw7kwnsE391$>Kk&9?GuCcCa%sd_O@EK zHY|VjmZgiCE!!{a|J`j-F+zwvtY{%OPvP5c=?kK7%+ooC;Ip$0J}O!SynN9StIAQgHYI;rlVp)#8WY>a)H+V%0_$O~~3_xh;k zgOql)7N!CxS0`MSre7GBy$lHTdgFp@b|7UB?z{HA6gOP3>D{7^TAUbRb8pia?JCeL zMEO3I)^QXuC51G7Qo&W2e%;2z0NTpbhW;yJux5 zdk5#=BcvZaiV(z#CUN5@F(fQ`97Hb3qw1im^NqVt1(G_BGD+-vr@L$`tx&qrNmr&C zmpexS!R_ZvY)&N(*)IA;YXJl=K9c1CZdcW-oFlVDGJaHjC~?*)-qyEMQcoYS;eezz z5mjrbN@-|;os2lpqD6Sg@t2>eS=saLz#|5`Jt-(E{C4c{>H-%^=KZ7EhH8W~84yxR zQ!S%x?Msxp;X}Hna_WW@iF4*1TMqU?kQ4l&%sYpzV862}fYc@g*}rKS!vIVyk8Cjo3e!LU+Qp;QmvEr>_k9EhKw z$xbj-Nvq1mvqEw-qG_vHQzc5t1c_|b>ztj;y2BS@13uz-BPj1cSG~*nhN7m~`--&} zt{r&;dJd6Ic1lcXVuS$J+4Yax_=RzK66tG%?NR^~5ux3Z<;CH_ zNrx{$VR)2&TSAa&pFHzs`6_usdkJO5W*i!CJ{(E#=bO*}fsC;Xk{n z)#l)+1=KzGkf05;_xK+d<8JR{ZESCE{kNCtPvArOWyqC*K42kKGU(tM_$#4^TC9x5 z)w`**4nNUoyHvwDLr3mS?jAKG^Jv`S3AmKkESv^92xxJ*YC9m64NO>uHSj;)6{;5| z3reX4BzZD01b1E90j`na-gp-#DBwSneW|f=@+p3p-|iCWI(u7KfFJiEK}L;i5MscN z0F&|K>4fRmd7h5xB>BlJEJH^?XikifuxMH(QDO)QL@T%7;f{hqXI$qF$mAlrCGkYG42hjIJr zUlVs*_;G$_?TZjY`4LaL|vy5}Y!*A&rW-AP)jbSQXE z>A0NjE*34*MjPh7b|kefRow_?pkpgUIe0_Qj$PC%bHe`?=a~1xobZ($RIL=c)KG#g zVYfs1x1R{T{$vlmp-4?On2Yq!8_XTU2y3F+_bp<;Btr2gqpeEsRs`|$buXa#tIbvh zwhlD$X5WzGP~F5txqY!zboS6Zu1(6bs_a5S-Oks7^_Wzv_yp=dSMeEwj4O{>CG}-F z1pH^o^ZA+cW7!`L*O2F647Ks4EPV|5+nza3B>O^!$o4b8JF$`3L!i{B2Cl>K=)j*S zU@mSbT=!yB>5lrk8J*d=EE23pHFA0tlNlK4`jHX{EZ?f`VfSGQ3@(%d4i}8lIkAC# z!_=C9LyfAdgDQpeaN7gZS%xYh^(vt`qjWB8;MnjxO@Mb9=&zUCp1z?uVZ5?yp%QSo zXrv30?HR_=1Q4iKAsj%j_TMD483=-k~LZD=yZC0{vjzK!kvV)=x202D?Kw6 zKe&--6H5SxWtRh$xbXJHD};?*EvSCk@3GfBg-Cw%4+9Bn9GlF21@U7=O%Jr6KF@fm zXYgTLpT`%br8++sSQC_{b$bsZutAD*aPf8?To7M(`QMLo$-Sl=)c$*`>%<0oT6aA z^_QJ}^3sL0<@?Nuv2m0`4}9B>8iuJyD1e{7c6Pex2Jzvuq%rPpqFkBB9#JO;Dl8$3 z7UV%A7R1U32J@VnceyJ+=^JS4H2-@tHF|l<_!NKcO1uQLuc(-gJu;QE-!V0FkG<`# zgvL3G-VOVpYFAwg;gy*-=^FcWfjxZrbWKT|xz(p3aWzxX>4m`S znSJCYGAxY`feC9y1LFg3Ic~$U7lInnqWa!fKr(L;@RZ>QTPN-&;8$CF0P&i!|4+g# ztio%anz&C<6K0B{gu`kXYZw!D*b|OHwFVg`34hs>^#%2kK4(rJd z>zZFPxOorz`RZ%FL-Ufz@{)XUn844t+RD&gK7z=Ip~{HS;N3@_@N%3exA6m?@Pjw+ zMA*;m)@GUb@QI1uQS6$7@u|N>clf*&NGf$h zVgl5z0nFid?>m z&G-i*ilU;=TB@x)#HJd@*prr@tn*yH6E@4c!At4eOMac{GWH$f^+FDhOE|pvG7_72 zFV!A8tr@2f-a1-!Bfh1~La%K&qQxbv*}%b! zr&u;lV~y{a?$b)%g`dp=*RM7I@)i9K*O>L)f)D)t$ z@F=)1B)Za%THsG|`NE-dEa-x(t3u%aR0^rM%oGpgD%zpIz(`*x^*>|x<}WSTnB8n` zKB+6%16h$C8A9A_@qv$cU;4m9P}*%F8^DEd!u$Jd%%-bS`o33Yo6>0~h%ep&Mk)Ja zZn8K@bZS#{ljRnRQ6g7nLpbc~6uqpexZ6Kf*nQTpn=xKX$ir5$vZ5+~t0jIPx}CMv zE(BZ%9UGL!Yr^;(Cs7vNqOq1rGaIf!g}|miR%Ff;qHo4|))8cKb&)-f8mIZpMsOf2 zh}`@>t7%LwZvIWX+bzN;+6bUvC*Fop9m98ikuJP>Iy?GlgOqP4CdFad;BW8)y}bgC zQm6RW39@S>LWJdsR>@=Xg-L57 z8?wnx%dg||a1mYyIf(I{u1nLKptfXWE9AGP44j43;_deDc1dV+_XIn-m@GFy0YK)| zL3mr6f)3KpS~k%;p57m!d4>8(Gb~YG4Btq~Y1(^D1tekd)Zm0?v6>F|kOj6+C36y@ zSrI94!XOCAW14A23o-BEH-1d1>Th+hHS<6AU{?K7oa~Jmd@)aw8ABBQh8&5@WBom2 zwl8Ampj{^>3Fm!O!&&I+Y7iSU{AF_TbMtY;>0NhkqlfZ5CBzz-7_@Iba>#FDZ`AuMB zqJzDKgadKSQ(}CQNh&tDh$#=M_T)(!To&52Qp)~l3Sx#lFWBLyy~?h#&wZKeI9I|% z$?r3+mA}~q(W^IcHj4`Mlj30a3r6~(RPIL zg%02Mro^$AQxlJ}3FTn8LDy={l*PDXa`y z(m?)e3Ol=a+L$^2dd#oA?T$`oMSH~VgG~fuLe?0{DUPGBpO8B(Sn0oLSd+lKd?O^E5MTjs}1K6CL>lNNQh zdw;T!G%k!|yE;;a?SDkKj?=@P6@i$twKE*dOLSiu2S1O5&SsPKA6l~j;gve z%$xfmIvt|mCd?)0Gv?jqrL=w`ly>9%sV+T{X#woM6YhOi^;T)bXZ%--@?*7_rPlN( z?B=VBv$jlQ59Q;a&_OlH!&!ULfyaoeWNfm3ydiQdjoWnR-V!{*f#`h^7eT9!_7&K2 zhGzM;{Zxu$Lxw75L|B?)9rJ#PiZ=yN|FuV08O=}PZeEm23V$OMGvnS-*yF zeuN>GK(9Eak>y;%!3(m2M}Xr)#;V>^=ALKTyH`mn?sX?viCXJ5NF9FmDck^nBk4@% zE`BBVI$7ln_}ke~e=T(2ea4muKl-IE?aCY_rS96z^$Z~Lkzk6nmA zo^$n8cQlKmRSwhen$2VEPXwYWn4@&zxfV@ctj8p==6ILTcM2sychc0>X_!Qs@`m`F z_bW;VkynmSHy$@&) zMM*kZyztWY?7H-?#hZZ48ayN46by;*$7O3nY6|_T(KU)$_?+zIc6vtp(68g`)&YC| z3V(f6H@-=cq+ykxFo8-&>Nrea=BY!VZq=WF+dE!TN_nWyq=dQ%*NkBLK81M0Lv`Eh1N!v^-WE7 zN_0`yS4EX)T?hs82K73YV7QQES;Fy}C)XkxF7k4)O4=d}!W|QCfiP!_|SP8U9 z-%r>V?I`MmepT=3>#{Nzd22m5JtOTOIP9AU-6C_HH;WC&jx4~RsWsu|bKQ5G9XYb% z!fA`Yxqa@z+b}v4;XnwrsnVL&lljA@GhY-_IH7Gjdyhh7-i^}DZUNx`%n z+!n@WAd?K}?p+h{mx)@}MD@kRWyV6IfbsNA%Pad-iZ+CA z_QcQV#V$Y!mK}87dKqMPOcA)ukQ6IrLWq2Lwxpbp+q!`= z^i53P#tyilji}I@Qu{O^%^WS6mEc=6N&Kx0=RN0Xo1d@+lGE23ZL4|7TG-&pcpIEw zxET8vJU(@umuCnPVPcFYBEpD<%h*k;r#;PT0IOZTR-!w^rF-K5_~d6SE^g zpEnZ=?|OM4@FWeiDOUt~gFjEN@br}426pkiXZD>eIBotRlrz)FL*Z-QJsY9BE@`LR z_p^d+Ws#Ga)=RlXj}6ioBdk#)1`ZVjSI4c&{X4lAKLY{khZ?ed{)By>d_L=0(@ zMBGBz+{;&L9s3M2eHy%-5*!T}$#`wsdxMUOYE2k!4X6<8&8>VTUS@3Og%=x4Nbroh zq1qT*3i`+M`{@}KUgU1~$?n~Ni${lHDb!toeZwF6;uU_^YuopB2?Emc8J_*<;4Tsn z6rTuTaB$goluzPgVKBkR6NlfNK?Ir>68fjyBeq{4HPc~Flne8{mtYJEQ8bvL!oUiz zLV_m4b=p2XO|Wv0T)bxtunkscH=V~F5fAGY;&2jQQm4ACSfNJz0Nhd^Z^iGR2FUe# z*<~`(JOd5pgz9jGBro$)H;HRMI;VRz^+=RGYb_Apv2XA>0QuJ;4fZe@#q<5TeZ#~3 z(MydxS}K+9s4@iVyw3wj(;pUq`PXZkNIr9=It8W-=pu5kJ|yulCXu>7I1OX4jLQqF z%Li82kUaghE|GHH@os#SNWgkLAdK}UD;@Ml9R^DF$diHXIUI9`6iXZ=b1-3pxL232ZLXoUhd0&*NxTsa# zvbZP{1DTd9y5^1owP~ByT4^pw)P?S zFh6LY_Iv|}w3{Xs+5M7Dpd2Uh5hpumOd~f}`R7_Qjn8#-{W8{0)bPBIRui}}<9Y#4 z=8$zevTw-MbutcFGrtU!78&%3`wt%`e3IAPs4AmRu=p_ivq&PtjmRynC=?of3G7}Z z1CFe0dC%3;n%FoFdl3tP+uc$Sv+yoC1JuPsmWa(d&4s&D*pxhFBRRY{8knWD;@Y1z zmJfdlG7%Uh+PZJsbA5-kno)W?t5f>jl6>zQB%9RZY}BcS*awsmIq>%A>mxO#C>qh@ zV?$!3gdmpM(^}5-%*nlB@~n)X1Uo%)O0t(nO-U1&Y=v?*lJ&y`2O^%0F$2rJTshl7 zYg5RtOzhY@>o`UeweC~5u3w!RwAAL1eXR=&WA-<8?CSSEW49Q$m&uIhe?Fj zqW%z2>MXQ+gYgsN2&UedD-Xm(EG>G#YqHXIJ~ecbz!diLXoU1`8g5k_h`aG z_BR*JmJkAof=-C&SFdyfkG&pY1kH*c?M4_C8>OGgLJHZ^P(%$0J?|iq^r@@4p31^8 zo#fa7YI~|N%sTY04xb?hyJ+j2a;RI`g$*d91hV-`=cHKrh|B4tT?=lt?6Da4m~L&q z?;^Dma0u9_J4L3$KQ#Gs7V0?5CZ^esx(x{e^D`xe5hik3Av+- zyi&ODo^-gc*>{zaH<4d%%Yi5G$o7KiT&js$yMqi$8zBH%G!ckxI;rhlXj^TMxUM6afs(ljrYO@c$b6KZ9PMuJ4@3ixcu39&uPwO?AFo zL8)OecFQUKz$TsBW^|PpNplSa}=zbyr%J`JFvR`XKujseuSwQ)|+E<*4Y0 z*R>a;VzT$X^5Q30nAKH-SDN9(r!hC%JQKG4hz}wn@9u^@ zo2-+4D~V4=_FIOOF1)!~1xaGGuNvYdJlowAn z`NGYtw(+Z(e%5p1PyTob$J4SVj?o6!C-TlxoSO*~?Zw^d@u zviXl1gA>O^^O~+C^HnG5X{PNg322zxUhknD1O@*QvA``KXTX!$%*v1XonIMy(UJD=H6ebCJ&;`&^> z=x69#2!2X%Hpz|V3wgc_W4F=uXaiYkzv5Muh9*;$({|r{?j&$0k+rqL%cvOWO@QGy5CV zLQ72FsSxXxK9V~0H10#xm8LZAbkr4(H11(oTOWn=A3@yU4XLG%u0YF&hS{c^yT#eN z<}4iyfbhaNftgm_j5VLGZuy9vsjb3ox zLN1WjRE)aV@N$DDIj6dsF>Iz0mZJWOH)0SjD@9nv_Qhe|rD4{UVJBVM%}L|Y0}g!U zVb;JZE@gIEe?`Q!NILV`TrgK;iE}%N^CO9As@{>>qm!XpTlb?^ZrYmIsL?}~8iKt^ zt{UL{#~S>FfdpT+Hoj~DOLIp%KG_rO$JqnFR@(#5KzLdM>heJ9*G0B!Bq*NZ+JU;- z5Z>A@=N$+(+hhnf6hbIA-abT2+&++rZ;n%1W(^8nD;N>1k6^5fVtfOA#xo(g8@-82GR5pMUXBl{_=@{6x^aaFqQB5KQiv04Z zB!rz)cZKly*Uu%WwGtLkDZvs*DUs1!fEXm=F5xghS2tFXzqlG)ZMSQxzFX>Bw^vKd z!$w_!a4djiN;W`DG)a{~e7`>=c?YN!er>mJs=i<9TffvQGdZXf!q;qocoJ)B8%R?~ zUeX*SUP>G!56f^fZV%Sl2-ewfR>(@qVI(cIS1?C$HZVuC=NtpzGUi=!jKG9OYOXrT&us!>IO1DGz;R;0bWcVAK?p;BAz4NGWV4VyIqYM}A{prX#>sX1E&rcHNNQ>KIHI9lmB%IP^A-lk1cGaWN<4hWBbV?+6lhJZvj zqe;se71tqFd^eCtoS(W}o@!a18n8N(2qR9ljwpb5r4MpRkis}58hnR zYmQb?j&f0sDFFW5W=&rXctUnA7r=?o7OWOp!D@3ylTzX&EjJC7dHk4pypDOiJ48ku z@;X!w5=B}a(qIPu^_hp$UNR{SbrSiFywNyp=AK*To=)c8Te9e;c@Gmi)s>DnNFngA zB!|MrXoh4?Rd+h*D()=qmn!D;MBXE*%A3b_dwnNlw_wVY*i)w9k8ZkBmW^$7;eXX+ zk6n^$YU+t_U6?<4kPcU00iSa4CtE}xBtt;xSQSRj_2p&?FxB%ol)+gGR z?}9QSx1jjYBe3pfQkH`N&aD9Fa=>MELA-W&s4h0&Uc#NVDy0j6KbD$fHD9`G_+Cvo z6_N+r(!s{g-KN6TMi@uKi5fI)MQLmR-sGbQs0>9}3YvXS_={KzZif!m!t2k=s};+7 zrOSkZX@%UO?9(>Ux$-6i5-HJ?o5E4Hn`G#=(Y5;nOT=%|ffDJ~66w0;A1JzZZiHau zm5LXJz6WzT#q+^C#e32@*tIFs!p!5i&F|^V<801QHiCbAQx84D4sW;PvW4&YI*@?Z z5N%n~uFZ}XW*NtA8AoRs=WTj4SVBUD){?DfRK|n>1x-U1*nVG)>druEsBx98QKM~6 zy)8JuLLk9e{8Gbfed_M03`HXfR2c`z{m5_JPTO1(Y%M{(6+p4~h_JVu?P0x~8mqYQ z_5+{Yo#gGBNF^W?^*F&Nh83mb2r5~_yBj~OHGWuVgofjSx9gJI0z!O9h2nAIPmRhL z8=&rLChdt@^=MZ?>R~$SVXEt48kmsvGa&DBVP}+7tmGvx;#h&Oht3&B&d6xUABxf> z>i@jjQ?V*mx(bnzM&0OZzz1q3fY8ce?>}py7@M#$h}C?)l82X}yOgPGk*VviKKo6w zgnA|_!@w6SAzfPf)9bV_3Cf{iKGE=14`@}S8K$Edrn(uXffZRjDh%Fs`7#2&c9^gX zMSIBo9R$a~Rf+}B4HBs$EifG|Fx4$E0Rq!Pc&xal?RI|1QabVXGAXB9dO^~NFw;30 zwc&k7Svg***R`kze&Dl;UuX8>ItMj$0yP{y&gDt?AxVsO3d0+!(BM->%!$)RQjz|;AZi@;8U>Q8pO@GB zGoyYWtnggXwMZ5sU+Kog#rpC{?yZ;OyM20=(l$Tq(`n|(nvnz5@~4t`ZKl%q#5D;V z!1j}kY$(etfG2Z}AHw&?%!9W-*JfQ4CA1$`-+dsgED};{iYpwJTjt^2I}RetqxvGQ z>-pt!kHMg3YyBK2L5Z+-@ku+NCQU;r=1X>j!Z(&jZ2dOvO0i_d>wYVuvh{3|rmMpS z1!r4Nk`uQt*YC|FDxMhJQf)`~)z)lDa&Ls<+`Nt5_!1YJ=qDXLg}BUYaqGnI(%bZE zXgqbBD!$a0lC#GdwWbsDj;}ytoJQG>>M-bQavrb~hi>6*j>9 ze0NZa&o#WUwAk-$=4I}Tu)k^WkzpOBWx8rREh?2!Ilw`=v|Qcp z0l)Kvc=le^cTcq3sdKWCow;#RiVLHark-BgW#j$O&~zYKNgV}q%BlGFN zSvS;Y$bW{NBcm$+vY}l{a#{T4H2u_VhtJCHPXUV1wNxN zE6l)6R2nCtk()5?=PNTD$IAulg(>wBH`B;?tZYO3=Sn8+?m&#QhC9J!pJ%NOW6NV$ zR>Vm(R~?RhbeRyY9uhEFVzI7{_ea9Sys@SB`j%c|eY5^e^+&hXcenyzSD;SKr`%vbzH3Tno zt|_x2u)7?aeKEFFO6VhGBR`rbw>WouzNBu}nR?D9-b)tDVcFq0@)*H|vt?_Ko z2_&o^vRBI%fzJ2!3qIY?%@cV0s84)rX#!K|_<3+k_5Acms7Q1FHCWwW61`Cd_(gnxl3g29Fn8n$J#>rD^%? z7VRNC)G)z5XA*~lV;$x|y$&Om1y4N4L3*7^JOZA$@%nXv(3d)MjRR%_)0=c5;k9Rc zruWaB2M>js{N1hS>tqgs-RE$Fa2fIr>^<-hMVJ}U4&hzPQ05dFWDdgJcX0cStkMA- zg+uL7lg@3jEb?OB2S6lo@$sp~#jtL8}$otS~Fg%H3UNA{?dU$`8U|C22R!+^Y zQ-WZU_H+PF!l;m1NyyA;G(2RqJTefDBOC|^0|Epc0)jUCb;=Via$U8Hwz^QPC(RY# zsuT`U8X3I=fx4Vrs|=vZ5J-hU-A=Cc1)$0pXof&NPOen}P(5aXnWyJkv5AvpEZ2dU z!$5SF^Vf}xz*ZdTZ+i1JUq4a~Tk)X3N&aiTVdN;bBEo{h)S0?_+;UHZ1tLpLa0vW6 z4|rq>y)uV(qhL9#3Z6)ZlAfy&bY``tb=IC;ghhgm-Opc32q|i>@TM0``a(jIQ;Z1k zC7V)~rdWHZK*#9JRNS1A4zH?njDknQkdZf>Ko_u$TXu@D7-fPuWD3OAgL` z_ah+ciF9Im{c8)ec{oLW4q`H)TzHoWXfjXU?!R^u9wffHev$h=;D>@o0eQfCjQ`aG z{$4+S%h&o!n1y4yz3)l!SAACy=lJJmF&Nd4~{+?X-GQX$a2E_A&2# zoy-I3mP(PlEh1JV4Re3wUK>Ya8%R@dU_NMxLSsNZ4y$r0OEMhHh*|LQ;u~lEj?9Vz zJ)${VdU+=MFoVEZi!TfNS)VqxXTM?oe8wnyT&G(b8tz6Gu#w2{a$BZeAfu}^fnvk? zs@yNmYX`|(<}zMWftg{PQ-y@apEO`vp&Sr+-P%xE!5j#9{n|)c zksL61=~XI=yHl=r#SGWtO}c><3~dYmvI#f&_8EA#T*@^^{bie_}`5Fl!>4*b~vmFUOKy5SU%H^UjbP)b%3@m@Wh`f$n zg=P-L8dwWg1!s=M8eWT6g=db$%59WaahP*>ucCRR)Mbai1kMD~6s?Ai(7i*q zS4gL?egiK5lF-cnpMTQGoDc&p3|taT5=NRV9|lhxkAO5NR>5dvxmlOHv64xc<|0Ki zO5@vAyZxlF&5!q%HHPnQAgK;cY{fgLPPvr?WtwdQgtOpt?1FAI$@W(;*!MrluDC;Y z=u>K}5XPq+!Z+W`=_TK+MFc##)CnkUhH;v$MQ`5Zmp#LEW?+_}VtGw7s~UJr2v{83 zra3o`Z+N&;Ogw&GBc@(OtF!NZ${zc#fhrojTmHPho@*~hce*gG`7V7`C z80jUz%UYMe#KFM)!RJ5_|5f?&Qt)K~$REL5&?@qu`iOrk2YHG0vby3A);@^z{Rivs zT8ozeFH0T%0HlLl>^}ki6h6E}d0A8N2gL(KPY1)1Tl~P zH@fFbl$S)xKPVU|zfu0?iv49{|IHZtU3K&l@Fj`y58(a_z<;AOzC?RTUi*V41gho$ zDf##9{r8Q%M0v@|`h)TX6c~U|{&2KjioPVn{1LUo{w@0dQDa^ryyS%ZK_~&emw_(+ zk|FXE;AKwm55NK8Z-D>K5WWU5)uEJgL(=0GBfiB@Pg$30Q{4u zc?tM3Ir0avi}WSnpH#_9l$Y%XG>R!dn98svPyz;Hpo Mte|hcoWG9#9|~3(D*ylh literal 0 HcmV?d00001 diff --git a/pyproject.toml b/pyproject.toml index 4c97efb..3606611 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,6 +61,9 @@ docs = [ "mkdocs-minify-plugin>=0.7", "pymdown-extensions>=10.0", ] +aspose = [ + "aspose-cells-foss>=26.7", +] [project.scripts] excelbench = "excelbench.cli:app" @@ -121,8 +124,8 @@ module = [ "plotly", "plotly.*", "numpy.*", - "pyumya", - "pyumya.*", + "aspose.cells_foss", + "aspose.cells_foss.*", ] ignore_missing_imports = true diff --git a/results-2026-09-08/calc/README.md b/results-2026-09-08/calc/README.md new file mode 100644 index 0000000..5b6c97c --- /dev/null +++ b/results-2026-09-08/calc/README.md @@ -0,0 +1,18 @@ +# ExcelBench Formula Recalculation Results + +Oracle: libreoffice/LibreOffice 26.8.0.3 bce0998afefdbc355585ca324285661a2170ba77 + +Formula values are compared with absolute tolerance 1e-6 or relative tolerance 1e-9 for numbers; strings and booleans compare exactly. + +| Engine | Status | Matched/total | First mismatches | +| --- | --- | --- | --- | +| wolfxl | failed | 55/133 | Schedule!B11: expected -308872.0, actual None
Schedule!B2: expected 100000.0, actual None
Schedule!B3: expected 38000.0, actual None
Schedule!B4: expected 62000.0, actual None
Schedule!B8: expected 400872.0, actual None
Schedule!B9: expected -300872.0, actual None
Schedule!C11: expected -306442.0, actual None
Schedule!C2: expected 104500.0, actual None
Schedule!C3: expected 39710.0, actual None
Schedule!C4: expected 64790.0, actual None | + +wolfxl: 78/133 formula values wrong or missing (first mismatch batch: 10 shown, 10 missing, 0 wrong) +| libreoffice | passed | 133/133 | — | +| aspose_cells_foss | failed | 25/133 | Schedule!B11: expected -308872.0, actual None
Schedule!B2: expected 100000.0, actual None
Schedule!B3: expected 38000.0, actual None
Schedule!B4: expected 62000.0, actual None
Schedule!B6: expected 488.0, actual None
Schedule!B7: expected 719.0, actual None
Schedule!B8: expected 400872.0, actual None
Schedule!B9: expected -300872.0, actual None
Schedule!C11: expected -306442.0, actual None
Schedule!C2: expected 104500.0, actual None | + +aspose_cells_foss: FOSS FormulaEvaluator returned no value for 107 formulas: Schedule!B2, Schedule!C2, Schedule!D2, Schedule!E2, Schedule!F2 +| zavora | failed | 0/133 | Schedule!B10: expected 0.0, actual None
Schedule!B11: expected -308872.0, actual None
Schedule!B2: expected 100000.0, actual None
Schedule!B3: expected 38000.0, actual None
Schedule!B4: expected 62000.0, actual None
Schedule!B5: expected 12000.0, actual None
Schedule!B6: expected 488.0, actual None
Schedule!B7: expected 719.0, actual None
Schedule!B8: expected 400872.0, actual None
Schedule!B9: expected -300872.0, actual None | + +zavora: 133/133 formula values wrong or missing (first mismatch batch: 10 shown, 10 missing, 0 wrong) diff --git a/results-2026-09-08/calc/aspose_cells_foss/financial_model.xlsx b/results-2026-09-08/calc/aspose_cells_foss/financial_model.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e1787250848269844dae57cd468bb5f1134f0dcf GIT binary patch literal 9655 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 z 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 EAFR!wssI20 literal 0 HcmV?d00001 diff --git a/results-2026-09-08/calc/results.json b/results-2026-09-08/calc/results.json new file mode 100644 index 0000000..d3482d5 --- /dev/null +++ b/results-2026-09-08/calc/results.json @@ -0,0 +1,187 @@ +{ + "engines": { + "aspose_cells_foss": { + "matched": 25, + "mismatched_cells": [ + { + "actual": null, + "cell": "Schedule!B11", + "expected": -308872.0 + }, + { + "actual": null, + "cell": "Schedule!B2", + "expected": 100000.0 + }, + { + "actual": null, + "cell": "Schedule!B3", + "expected": 38000.0 + }, + { + "actual": null, + "cell": "Schedule!B4", + "expected": 62000.0 + }, + { + "actual": null, + "cell": "Schedule!B6", + "expected": 488.0 + }, + { + "actual": null, + "cell": "Schedule!B7", + "expected": 719.0 + }, + { + "actual": null, + "cell": "Schedule!B8", + "expected": 400872.0 + }, + { + "actual": null, + "cell": "Schedule!B9", + "expected": -300872.0 + }, + { + "actual": null, + "cell": "Schedule!C11", + "expected": -306442.0 + }, + { + "actual": null, + "cell": "Schedule!C2", + "expected": 104500.0 + } + ], + "reason": "FOSS FormulaEvaluator returned no value for 107 formulas: Schedule!B2, Schedule!C2, Schedule!D2, Schedule!E2, Schedule!F2", + "status": "failed", + "total": 133 + }, + "libreoffice": { + "matched": 133, + "mismatched_cells": [], + "reason": null, + "status": "passed", + "total": 133 + }, + "wolfxl": { + "matched": 55, + "mismatched_cells": [ + { + "actual": null, + "cell": "Schedule!B11", + "expected": -308872.0 + }, + { + "actual": null, + "cell": "Schedule!B2", + "expected": 100000.0 + }, + { + "actual": null, + "cell": "Schedule!B3", + "expected": 38000.0 + }, + { + "actual": null, + "cell": "Schedule!B4", + "expected": 62000.0 + }, + { + "actual": null, + "cell": "Schedule!B8", + "expected": 400872.0 + }, + { + "actual": null, + "cell": "Schedule!B9", + "expected": -300872.0 + }, + { + "actual": null, + "cell": "Schedule!C11", + "expected": -306442.0 + }, + { + "actual": null, + "cell": "Schedule!C2", + "expected": 104500.0 + }, + { + "actual": null, + "cell": "Schedule!C3", + "expected": 39710.0 + }, + { + "actual": null, + "cell": "Schedule!C4", + "expected": 64790.0 + } + ], + "reason": "78/133 formula values wrong or missing (first mismatch batch: 10 shown, 10 missing, 0 wrong)", + "status": "failed", + "total": 133 + }, + "zavora": { + "matched": 0, + "mismatched_cells": [ + { + "actual": null, + "cell": "Schedule!B10", + "expected": 0.0 + }, + { + "actual": null, + "cell": "Schedule!B11", + "expected": -308872.0 + }, + { + "actual": null, + "cell": "Schedule!B2", + "expected": 100000.0 + }, + { + "actual": null, + "cell": "Schedule!B3", + "expected": 38000.0 + }, + { + "actual": null, + "cell": "Schedule!B4", + "expected": 62000.0 + }, + { + "actual": null, + "cell": "Schedule!B5", + "expected": 12000.0 + }, + { + "actual": null, + "cell": "Schedule!B6", + "expected": 488.0 + }, + { + "actual": null, + "cell": "Schedule!B7", + "expected": 719.0 + }, + { + "actual": null, + "cell": "Schedule!B8", + "expected": 400872.0 + }, + { + "actual": null, + "cell": "Schedule!B9", + "expected": -300872.0 + } + ], + "reason": "133/133 formula values wrong or missing (first mismatch batch: 10 shown, 10 missing, 0 wrong)", + "status": "failed", + "total": 133 + } + }, + "fixture": "fixtures/calc/financial_model.xlsx", + "oracle": "libreoffice/LibreOffice 26.8.0.3 bce0998afefdbc355585ca324285661a2170ba77" +} diff --git a/results-2026-09-08/calc/wolfxl/financial_model.xlsx b/results-2026-09-08/calc/wolfxl/financial_model.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..17f0223e0d15beba930a2081fd1a996944f0f022 GIT binary patch literal 9894 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 literal 0 HcmV?d00001 diff --git a/results-2026-09-08/calc/zavora/financial_model.xlsx b/results-2026-09-08/calc/zavora/financial_model.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..9074d5b0625c672fb88394c552a7e480e249759f GIT binary patch literal 9022 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 XrOH6q=ZY}|1j_I4v#t=4{eJp?Q#TL& literal 0 HcmV?d00001 diff --git a/results-2026-09-08/cross-language/CONTEXT.md b/results-2026-09-08/cross-language/CONTEXT.md new file mode 100644 index 0000000..452083c --- /dev/null +++ b/results-2026-09-08/cross-language/CONTEXT.md @@ -0,0 +1,20 @@ +# ExcelBench Cross-Language Context + +This snapshot is for ecosystem context, not Python migration decisions. + +Use this snapshot to answer: how does WolfXL compare to mature spreadsheet tooling outside Python? + +Included adapters: +- `zavora-xlsx` + +Artifacts: +- [README](./README.md) +- [results.json](./results.json) +- [matrix.csv](./matrix.csv) + +Interpretation guidance: +- Keep this separate from the Python hero table. +- Cite the artifact path and generation date. +- Treat write-only adapters as ecosystem context, not drop-in migration advice. + +> Do not compare this table directly against the Python-first hero table without naming the scope. This run exists to position WolfXL against non-Python spreadsheet tooling. diff --git a/results-2026-09-08/cross-language/FIDELITY_DELTAS.md b/results-2026-09-08/cross-language/FIDELITY_DELTAS.md new file mode 100644 index 0000000..a91d7e9 --- /dev/null +++ b/results-2026-09-08/cross-language/FIDELITY_DELTAS.md @@ -0,0 +1,3 @@ +# Fidelity Deltas + +Need at least two runs in history.jsonl. diff --git a/results-2026-09-08/cross-language/README.md b/results-2026-09-08/cross-language/README.md new file mode 100644 index 0000000..8ea1f07 --- /dev/null +++ b/results-2026-09-08/cross-language/README.md @@ -0,0 +1,451 @@ +# ExcelBench Results + +*Generated: 2026-09-08 05:37 UTC* +*Profile: xlsx* +*Excel Version: 16.105.3* +*Platform: Darwin-arm64* + +## Overview + +> Condensed view — shows the **best score** across read/write for each library. See [Full Results Matrix](#full-results-matrix) for the complete R/W breakdown. + +**Tier 0 — Basic Values** + +| Feature | zavora-xlsx | +|---------|:-:| +| Cell Values | 🔴 | +| Formulas | 🟢 | +| Sheets | 🟢 | + +**Tier 1 — Formatting** + +| Feature | zavora-xlsx | +|---------|:-:| +| Alignment | 🟠 | +| Bg Colors | 🟢 | +| Borders | 🔴 | +| Dimensions | 🟠 | +| Num Fmt | 🟢 | +| Text Fmt | 🟢 | + +**Tier 2 — Advanced** + +| Feature | zavora-xlsx | +|---------|:-:| +| chart_anchor | 🔴 | +| Comments | 🟢 | +| Cond Fmt | 🔴 | +| Validation | 🔴 | +| Freeze | 🔴 | +| Hyperlinks | 🔴 | +| Images | 🔴 | +| Merged | 🟢 | +| page_setup | 🔴 | +| sheet_protection | 🔴 | + +**Tier 3 — Workbook Metadata** + +| Feature | zavora-xlsx | +|---------|:-:| +| Named Ranges | 🟢 | +| Tables | 🟠 | + +## Library Tiers + +> Libraries ranked by their best capability (max of read/write green features). + +| Tier | Library | Caps | Modify | Green Features | Summary | +|:----:|---------|:----:|:------:|:--------------:|---------| +| **B** | zavora-xlsx | W | No | 8/21 | 8/21 features with full fidelity | + +## Score Legend + +| Score | Meaning | +|-------|---------| +| 🟢 3 | Complete — all basic and edge cases pass | +| 🟡 2 | Functional — all basic pass, one or more edge cases fail | +| 🟠 1 | Minimal — at least one basic case passes, but not all basic cases | +| 🔴 0 | Unsupported — errors or data loss | +| ➖ | Not applicable | + +## Full Results Matrix + +**Tier 0 — Basic Values** + +| Feature | zavora-xlsx (W) | +|---------|------------| +| [cell_values](#cell_values-details) | 🔴 0 | +| [formulas](#formulas-details) | 🟢 3 | +| [multiple_sheets](#multiple_sheets-details) | 🟢 3 | + +**Tier 1 — Formatting** + +| Feature | zavora-xlsx (W) | +|---------|------------| +| [alignment](#alignment-details) | 🟠 1 | +| [background_colors](#background_colors-details) | 🟢 3 | +| [borders](#borders-details) | 🔴 0 | +| [dimensions](#dimensions-details) | 🟠 1 | +| [number_formats](#number_formats-details) | 🟢 3 | +| [text_formatting](#text_formatting-details) | 🟢 3 | + +**Tier 2 — Advanced** + +| Feature | zavora-xlsx (W) | +|---------|------------| +| [chart_anchor](#chart_anchor-details) | 🔴 0 | +| [comments](#comments-details) | 🟢 3 | +| [conditional_formatting](#conditional_formatting-details) | 🔴 0 | +| [data_validation](#data_validation-details) | 🔴 0 | +| [freeze_panes](#freeze_panes-details) | 🔴 0 | +| [hyperlinks](#hyperlinks-details) | 🔴 0 | +| [images](#images-details) | 🔴 0 | +| [merged_cells](#merged_cells-details) | 🟢 3 | +| [page_setup](#page_setup-details) | 🔴 0 | +| [pivot_tables](#pivot_tables-details) | ➖ | +| [sheet_protection](#sheet_protection-details) | 🔴 0 | + +**Tier 3 — Workbook Metadata** + +| Feature | zavora-xlsx (W) | +|---------|------------| +| [named_ranges](#named_ranges-details) | 🟢 3 | +| [tables](#tables-details) | 🟠 1 | + +## Notes + +- **pivot_tables**: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +## Statistics + +| Library | Mode | Tests | Passed | Failed | Pass Rate | Green Features | +|---------|------|-------|--------|--------|-----------|----------------| +| zavora-xlsx | W | 133 | 63 | 70 | 47% | 8/21 | + +## Libraries Tested + +- **zavora-xlsx** v0.1.2 (rust) - write; modify: No + +## Diagnostics Summary + +| Group | Value | Count | +|-------|-------|-------| +| category | data_mismatch | 4 | +| category | unsupported_feature | 66 | +| severity | error | 4 | +| severity | warning | 66 | + +### Diagnostic Details + +| Feature | Library | Test Case | Operation | Category | Severity | Message | +|---------|---------|-----------|-----------|----------|----------|---------| +| cell_values | zavora-xlsx | string_simple | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | string_unicode | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | string_empty | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | string_long | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | string_newline | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | number_integer | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | number_float | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | number_negative | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | number_large | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | number_scientific | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | date_standard | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | datetime | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | boolean_true | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | boolean_false | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | error_div0 | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | error_na | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | error_value | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| cell_values | zavora-xlsx | blank | write | unsupported_feature | warning | RuntimeError: unsupported cell type "date" at cell_values!B12 | +| alignment | zavora-xlsx | v_top | write | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'top'}, actual={} | +| borders | zavora-xlsx | thin_all | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | medium_all | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | thick_all | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | double | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | dashed | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | dotted | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | dash_dot | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | dash_dot_dot | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | top_only | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | bottom_only | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | left_only | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | right_only | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | diagonal_up | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | diagonal_down | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | diagonal_both | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | color_red | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | color_blue | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | color_custom | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | mixed_styles | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| borders | zavora-xlsx | mixed_colors | write | unsupported_feature | warning | RuntimeError: unsupported border style "dashDot" | +| dimensions | zavora-xlsx | row_height_30 | write | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | zavora-xlsx | row_height_45 | write | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| conditional_formatting | zavora-xlsx | cf_cell_gt | write | unsupported_feature | warning | RuntimeError: unsupported payload part: conditional_formats | +| conditional_formatting | zavora-xlsx | cf_formula_cross_sheet | write | unsupported_feature | warning | RuntimeError: unsupported payload part: conditional_formats | +| conditional_formatting | zavora-xlsx | cf_text_contains | write | unsupported_feature | warning | RuntimeError: unsupported payload part: conditional_formats | +| conditional_formatting | zavora-xlsx | cf_data_bar | write | unsupported_feature | warning | RuntimeError: unsupported payload part: conditional_formats | +| conditional_formatting | zavora-xlsx | cf_color_scale | write | unsupported_feature | warning | RuntimeError: unsupported payload part: conditional_formats | +| conditional_formatting | zavora-xlsx | cf_stop_if_true | write | unsupported_feature | warning | RuntimeError: unsupported payload part: conditional_formats | +| data_validation | zavora-xlsx | dv_list_csv | write | unsupported_feature | warning | RuntimeError: unsupported payload part: validations | +| data_validation | zavora-xlsx | dv_list_range | write | unsupported_feature | warning | RuntimeError: unsupported payload part: validations | +| data_validation | zavora-xlsx | dv_cross_sheet | write | unsupported_feature | warning | RuntimeError: unsupported payload part: validations | +| data_validation | zavora-xlsx | dv_custom_formula | write | unsupported_feature | warning | RuntimeError: unsupported payload part: validations | +| data_validation | zavora-xlsx | dv_whole_between | write | unsupported_feature | warning | RuntimeError: unsupported payload part: validations | +| hyperlinks | zavora-xlsx | link_external | write | unsupported_feature | warning | RuntimeError: unsupported hyperlink part: tooltip | +| hyperlinks | zavora-xlsx | link_internal | write | unsupported_feature | warning | RuntimeError: unsupported hyperlink part: tooltip | +| hyperlinks | zavora-xlsx | link_mailto | write | unsupported_feature | warning | RuntimeError: unsupported hyperlink part: tooltip | +| hyperlinks | zavora-xlsx | link_long | write | unsupported_feature | warning | RuntimeError: unsupported hyperlink part: tooltip | +| images | zavora-xlsx | image_one_cell | write | unsupported_feature | warning | RuntimeError: unsupported payload part: pictures | +| images | zavora-xlsx | image_two_cell_offset | write | unsupported_feature | warning | RuntimeError: unsupported payload part: pictures | +| freeze_panes | zavora-xlsx | freeze_b2 | write | unsupported_feature | warning | RuntimeError: unsupported pane part: top_left_cell | +| freeze_panes | zavora-xlsx | freeze_d5 | write | unsupported_feature | warning | RuntimeError: unsupported pane part: top_left_cell | +| freeze_panes | zavora-xlsx | split_2x1 | write | unsupported_feature | warning | RuntimeError: unsupported pane part: top_left_cell | +| tables | zavora-xlsx | tbl_with_totals | write | data_mismatch | error | Expected values did not match actual values: expected={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': True, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 1}}, actual={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': False, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 0}} | +| sheet_protection | zavora-xlsx | prot_basic | write | unsupported_feature | warning | NotImplementedError: zavora-xlsx does not implement sheet protection writes | +| sheet_protection | zavora-xlsx | prot_password | write | unsupported_feature | warning | NotImplementedError: zavora-xlsx does not implement sheet protection writes | +| sheet_protection | zavora-xlsx | prot_granular | write | unsupported_feature | warning | NotImplementedError: zavora-xlsx does not implement sheet protection writes | +| page_setup | zavora-xlsx | page_setup_landscape | write | unsupported_feature | warning | NotImplementedError: zavora-xlsx does not implement page setup writes | +| page_setup | zavora-xlsx | page_setup_scale | write | unsupported_feature | warning | NotImplementedError: zavora-xlsx does not implement page setup writes | +| page_setup | zavora-xlsx | page_setup_titles | write | unsupported_feature | warning | NotImplementedError: zavora-xlsx does not implement page setup writes | +| chart_anchor | zavora-xlsx | chart_bar | write | unsupported_feature | warning | NotImplementedError: zavora-xlsx does not implement chart anchor writes | +| chart_anchor | zavora-xlsx | chart_line | write | unsupported_feature | warning | NotImplementedError: zavora-xlsx does not implement chart anchor writes | + +## Detailed Results + + +### alignment + +**zavora-xlsx** — Write: 🟠 1 + +| Test | Importance | Write | +|------|-----------|-------| +| Align - left | basic | ✅ | +| Align - center | basic | ✅ | +| Align - right | basic | ✅ | +| Align - top | basic | ❌ | +| Align - center | basic | ✅ | +| Align - bottom | basic | ✅ | +| Align - wrap text | basic | ✅ | +| Align - rotation 45 | basic | ✅ | +| Align - indent 2 | basic | ✅ | + + +### background_colors + +**zavora-xlsx** — Write: 🟢 3 + + +### borders + +**zavora-xlsx** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Border - thin all edges | basic | ❌ | +| Border - medium all edges | basic | ❌ | +| Border - thick all edges | basic | ❌ | +| Border - double line | basic | ❌ | +| Border - dashed | basic | ❌ | +| Border - dotted | basic | ❌ | +| Border - dash-dot | basic | ❌ | +| Border - dash-dot-dot | basic | ❌ | +| Border - top only | basic | ❌ | +| Border - bottom only | basic | ❌ | +| Border - left only | basic | ❌ | +| Border - right only | basic | ❌ | +| Border - diagonal up | basic | ❌ | +| Border - diagonal down | basic | ❌ | +| Border - diagonal both | basic | ❌ | +| Border - red color | basic | ❌ | +| Border - blue color | basic | ❌ | +| Border - custom color (#8B4513) | basic | ❌ | +| Border - mixed styles per edge | basic | ❌ | +| Border - mixed colors per edge | basic | ❌ | + + +### cell_values + +**zavora-xlsx** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| String - simple | basic | ❌ | +| String - unicode | basic | ❌ | +| String - empty | basic | ❌ | +| String - long (1000 chars) | basic | ❌ | +| String - with newlines | basic | ❌ | +| Number - integer | basic | ❌ | +| Number - float | basic | ❌ | +| Number - negative | basic | ❌ | +| Number - large | basic | ❌ | +| Number - scientific notation | basic | ❌ | +| Date - standard | basic | ❌ | +| DateTime - with time | basic | ❌ | +| Boolean - TRUE | basic | ❌ | +| Boolean - FALSE | basic | ❌ | +| Error - #DIV/0! | basic | ❌ | +| Error - #N/A | basic | ❌ | +| Error - #VALUE! | basic | ❌ | +| Blank cell | basic | ❌ | + + +### chart_anchor + +**zavora-xlsx** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Chart: bar with twoCell anchor | basic | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | + + +### comments + +**zavora-xlsx** — Write: 🟢 3 + + +### conditional_formatting + +**zavora-xlsx** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| CF: cell > 5 (yellow fill) | basic | ❌ | +| CF: formula rule with cross-sheet ref | edge | ❌ | +| CF: text contains | edge | ❌ | +| CF: data bar | edge | ❌ | +| CF: 3-color scale | edge | ❌ | +| CF: stop-if-true priority | edge | ❌ | + + +### data_validation + +**zavora-xlsx** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| DV: list from CSV | basic | ❌ | +| DV: list from range | edge | ❌ | +| DV: cross-sheet named range | edge | ❌ | +| DV: custom formula | edge | ❌ | +| DV: whole number with error | basic | ❌ | + + +### dimensions + +**zavora-xlsx** — Write: 🟠 1 + +| Test | Importance | Write | +|------|-----------|-------| +| Row height - 30 | basic | ❌ | +| Row height - 45 | basic | ❌ | +| Column width - D = 20 | basic | ✅ | +| Column width - E = 8 | basic | ✅ | + + +### formulas + +**zavora-xlsx** — Write: 🟢 3 + + +### freeze_panes + +**zavora-xlsx** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Freeze panes at B2 | basic | ❌ | +| Freeze panes at D5 | edge | ❌ | +| Split panes row=2 col=1 | edge | ❌ | + + +### hyperlinks + +**zavora-xlsx** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Hyperlink: external URL | basic | ❌ | +| Hyperlink: internal sheet | edge | ❌ | +| Hyperlink: mailto | basic | ❌ | +| Hyperlink: long encoded URL | edge | ❌ | + + +### images + +**zavora-xlsx** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Image: one-cell anchor | basic | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | + + +### merged_cells + +**zavora-xlsx** — Write: 🟢 3 + + +### multiple_sheets + +**zavora-xlsx** — Write: 🟢 3 + + +### named_ranges + +**zavora-xlsx** — Write: 🟢 3 + + +### number_formats + +**zavora-xlsx** — Write: 🟢 3 + + +### page_setup + +**zavora-xlsx** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Page setup: landscape + fit-to-width | basic | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | + + +### pivot_tables + +**zavora-xlsx** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + + +### sheet_protection + +**zavora-xlsx** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Protection: basic (OOXML defaults) | basic | ❌ | +| Protection: with password hash | basic | ❌ | +| Protection: granular attribute flags | edge | ❌ | + + +### tables + +**zavora-xlsx** — Write: 🟠 1 + +| Test | Importance | Write | +|------|-----------|-------| +| Table: basic 3-col | basic | ✅ | +| Table: with totals row | basic | ❌ | +| Table: no style | basic | ✅ | +| Table: single column | edge | ✅ | +| Table: header only (no data rows) | edge | ✅ | +| Table: with autoFilter | edge | ✅ | + + +### text_formatting + +**zavora-xlsx** — Write: 🟢 3 + +--- +*Benchmark version: 0.1.0* \ No newline at end of file diff --git a/results-2026-09-08/cross-language/WHY_FAILED.md b/results-2026-09-08/cross-language/WHY_FAILED.md new file mode 100644 index 0000000..4476130 --- /dev/null +++ b/results-2026-09-08/cross-language/WHY_FAILED.md @@ -0,0 +1,421 @@ +# Why Failed + +## cell_values / zavora-xlsx / write / string_simple + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / string_unicode + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / string_empty + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / string_long + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / string_newline + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / number_integer + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / number_float + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / number_negative + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / number_large + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / number_scientific + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / date_standard + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / datetime + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / boolean_true + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / boolean_false + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / error_div0 + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / error_na + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / error_value + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / zavora-xlsx / write / blank + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / zavora-xlsx / write / v_top + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / zavora-xlsx / write / thin_all + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / medium_all + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / thick_all + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / double + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / dashed + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / dotted + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / dash_dot + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / dash_dot_dot + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / top_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / bottom_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / left_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / right_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / diagonal_up + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / diagonal_down + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / diagonal_both + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / color_red + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / color_blue + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / color_custom + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / mixed_styles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / zavora-xlsx / write / mixed_colors + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## dimensions / zavora-xlsx / write / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / zavora-xlsx / write / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## conditional_formatting / zavora-xlsx / write / cf_cell_gt + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / zavora-xlsx / write / cf_formula_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / zavora-xlsx / write / cf_text_contains + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / zavora-xlsx / write / cf_data_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / zavora-xlsx / write / cf_color_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / zavora-xlsx / write / cf_stop_if_true + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / zavora-xlsx / write / dv_list_csv + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / zavora-xlsx / write / dv_list_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / zavora-xlsx / write / dv_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / zavora-xlsx / write / dv_custom_formula + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / zavora-xlsx / write / dv_whole_between + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / zavora-xlsx / write / link_external + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / zavora-xlsx / write / link_internal + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / zavora-xlsx / write / link_mailto + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / zavora-xlsx / write / link_long + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / zavora-xlsx / write / image_one_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / zavora-xlsx / write / image_two_cell_offset + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## freeze_panes / zavora-xlsx / write / freeze_b2 + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## freeze_panes / zavora-xlsx / write / freeze_d5 + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## freeze_panes / zavora-xlsx / write / split_2x1 + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / zavora-xlsx / write / tbl_with_totals + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## sheet_protection / zavora-xlsx / write / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / zavora-xlsx / write / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / zavora-xlsx / write / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / zavora-xlsx / write / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / zavora-xlsx / write / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / zavora-xlsx / write / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / zavora-xlsx / write / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / zavora-xlsx / write / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression diff --git a/results-2026-09-08/cross-language/history.jsonl b/results-2026-09-08/cross-language/history.jsonl new file mode 100644 index 0000000..c77275f --- /dev/null +++ b/results-2026-09-08/cross-language/history.jsonl @@ -0,0 +1 @@ +{"run_date": "2026-09-08T05:37:26.998622+00:00", "commit": "9a0b300", "profile": "xlsx", "scores": {"zavora-xlsx": {"cell_values": {"read": null, "write": 0}, "formulas": {"read": null, "write": 3}, "text_formatting": {"read": null, "write": 3}, "background_colors": {"read": null, "write": 3}, "number_formats": {"read": null, "write": 3}, "alignment": {"read": null, "write": 1}, "borders": {"read": null, "write": 0}, "dimensions": {"read": null, "write": 1}, "multiple_sheets": {"read": null, "write": 3}, "merged_cells": {"read": null, "write": 3}, "conditional_formatting": {"read": null, "write": 0}, "data_validation": {"read": null, "write": 0}, "hyperlinks": {"read": null, "write": 0}, "images": {"read": null, "write": 0}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": null, "write": 3}, "freeze_panes": {"read": null, "write": 0}, "named_ranges": {"read": null, "write": 3}, "tables": {"read": null, "write": 1}, "sheet_protection": {"read": null, "write": 0}, "page_setup": {"read": null, "write": 0}, "chart_anchor": {"read": null, "write": 0}}}} diff --git a/results-2026-09-08/cross-language/matrix.csv b/results-2026-09-08/cross-language/matrix.csv new file mode 100644 index 0000000..64eef0f --- /dev/null +++ b/results-2026-09-08/cross-language/matrix.csv @@ -0,0 +1,23 @@ +library,feature,read_score,write_score +zavora-xlsx,cell_values,,0 +zavora-xlsx,formulas,,3 +zavora-xlsx,text_formatting,,3 +zavora-xlsx,background_colors,,3 +zavora-xlsx,number_formats,,3 +zavora-xlsx,alignment,,1 +zavora-xlsx,borders,,0 +zavora-xlsx,dimensions,,1 +zavora-xlsx,multiple_sheets,,3 +zavora-xlsx,merged_cells,,3 +zavora-xlsx,conditional_formatting,,0 +zavora-xlsx,data_validation,,0 +zavora-xlsx,hyperlinks,,0 +zavora-xlsx,images,,0 +zavora-xlsx,pivot_tables,, +zavora-xlsx,comments,,3 +zavora-xlsx,freeze_panes,,0 +zavora-xlsx,named_ranges,,3 +zavora-xlsx,tables,,1 +zavora-xlsx,sheet_protection,,0 +zavora-xlsx,page_setup,,0 +zavora-xlsx,chart_anchor,,0 \ No newline at end of file diff --git a/results-2026-09-08/cross-language/results.json b/results-2026-09-08/cross-language/results.json new file mode 100644 index 0000000..5d31efd --- /dev/null +++ b/results-2026-09-08/cross-language/results.json @@ -0,0 +1,4326 @@ +{ + "metadata": { + "benchmark_version": "0.1.0", + "run_date": "2026-09-08T05:37:26.998622+00:00", + "excel_version": "16.105.3", + "platform": "Darwin-arm64", + "profile": "xlsx" + }, + "libraries": { + "zavora-xlsx": { + "name": "zavora-xlsx", + "version": "0.1.2", + "language": "rust", + "capabilities": [ + "write" + ] + } + }, + "results": [ + { + "feature": "cell_values", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "string_simple": { + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_simple", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_unicode", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "write": { + "passed": false, + "expected": { + "type": "blank" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_empty", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_long", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_newline", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_integer", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_float", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "write": { + "passed": false, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_negative", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_large", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_scientific", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "write": { + "passed": false, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "date_standard", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "write": { + "passed": false, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "datetime", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "write": { + "passed": false, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "boolean_true", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "write": { + "passed": false, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "boolean_false", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "write": { + "passed": false, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "error_div0", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "write": { + "passed": false, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "error_na", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "write": { + "passed": false, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "error_value", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "write": { + "passed": false, + "expected": { + "type": "blank" + }, + "actual": { + "error": "unsupported cell type \"date\" at cell_values!B12" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "blank", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported cell type \"date\" at cell_values!B12", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "formula_sum": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "bold": { + "write": { + "passed": true, + "expected": { + "bold": true + }, + "actual": { + "bold": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "write": { + "passed": true, + "expected": { + "italic": true + }, + "actual": { + "italic": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "write": { + "passed": true, + "expected": { + "underline": "single" + }, + "actual": { + "underline": "single", + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "write": { + "passed": true, + "expected": { + "underline": "double" + }, + "actual": { + "underline": "double", + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "write": { + "passed": true, + "expected": { + "strikethrough": true + }, + "actual": { + "strikethrough": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "write": { + "passed": true, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "bold": true, + "italic": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "write": { + "passed": true, + "expected": { + "font_size": 8 + }, + "actual": { + "font_name": "Calibri", + "font_size": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "write": { + "passed": true, + "expected": { + "font_size": 14 + }, + "actual": { + "font_name": "Calibri", + "font_size": 14.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "write": { + "passed": true, + "expected": { + "font_size": 24 + }, + "actual": { + "font_name": "Calibri", + "font_size": 24.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "write": { + "passed": true, + "expected": { + "font_size": 36 + }, + "actual": { + "font_name": "Calibri", + "font_size": 36.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "write": { + "passed": true, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Arial", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "write": { + "passed": true, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Times New Roman", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "write": { + "passed": true, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Courier New", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "write": { + "passed": true, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "write": { + "passed": true, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "write": { + "passed": true, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "write": { + "passed": true, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "write": { + "passed": true, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "bold": true, + "font_name": "Calibri", + "font_size": 16.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "bg_red": { + "write": { + "passed": true, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "write": { + "passed": true, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "bg_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "write": { + "passed": true, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "bg_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "write": { + "passed": true, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "bg_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "numfmt_currency": { + "write": { + "passed": true, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "$#,##0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "write": { + "passed": true, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "0.00%" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "write": { + "passed": true, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "yyyy-mm-dd" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "write": { + "passed": true, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "0.00E+00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "write": { + "passed": true, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "\"USD\" 0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 1 + }, + "test_cases": { + "h_left": { + "write": { + "passed": true, + "expected": { + "h_align": "left" + }, + "actual": { + "h_align": "left" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "write": { + "passed": true, + "expected": { + "h_align": "center" + }, + "actual": { + "h_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "write": { + "passed": true, + "expected": { + "h_align": "right" + }, + "actual": { + "h_align": "right" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "write": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_top", + "sheet": "alignment", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'top'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "write": { + "passed": true, + "expected": { + "v_align": "center" + }, + "actual": { + "v_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "write": { + "passed": true, + "expected": { + "v_align": "bottom" + }, + "actual": { + "v_align": "bottom" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "write": { + "passed": true, + "expected": { + "wrap": true + }, + "actual": { + "wrap": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "write": { + "passed": true, + "expected": { + "rotation": 45 + }, + "actual": { + "rotation": 45 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "write": { + "passed": true, + "expected": { + "indent": 2 + }, + "actual": { + "indent": 2.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "thin_all": { + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "thin_all", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "write": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "medium_all", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "write": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "thick_all", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "write": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "double", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "write": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dashed", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "write": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dotted", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "write": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dash_dot", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "write": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dash_dot_dot", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "write": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "top_only", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "bottom_only", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "left_only", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "right_only", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_up", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "write": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_down", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_both", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_red", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_blue", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_custom", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "write": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_styles", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "write": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "error": "unsupported border style \"dashDot\"" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_colors", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported border style \"dashDot\"", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 1 + }, + "test_cases": { + "row_height_30": { + "write": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "write": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "write": { + "passed": true, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 20.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "write": { + "passed": true, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "merge_horizontal": { + "write": { + "passed": true, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "write": { + "passed": true, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "write": { + "passed": true, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "write": { + "passed": true, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "cf_cell_gt": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "error": "unsupported payload part: conditional_formats" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_cell_gt", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: conditional_formats", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "error": "unsupported payload part: conditional_formats" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_formula_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: conditional_formats", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "error": "unsupported payload part: conditional_formats" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_text_contains", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: conditional_formats", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "error": "unsupported payload part: conditional_formats" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_data_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: conditional_formats", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "error": "unsupported payload part: conditional_formats" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_color_scale", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: conditional_formats", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "error": "unsupported payload part: conditional_formats" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_stop_if_true", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: conditional_formats", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "dv_list_csv": { + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "error": "unsupported payload part: validations" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_csv", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: validations", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "error": "unsupported payload part: validations" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_range", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: validations", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "error": "unsupported payload part: validations" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: validations", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "error": "unsupported payload part: validations" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_custom_formula", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: validations", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "error": "unsupported payload part: validations" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_whole_between", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: validations", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "link_external": { + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "error": "unsupported hyperlink part: tooltip" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_external", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported hyperlink part: tooltip", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "error": "unsupported hyperlink part: tooltip" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_internal", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported hyperlink part: tooltip", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "error": "unsupported hyperlink part: tooltip" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_mailto", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported hyperlink part: tooltip", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "error": "unsupported hyperlink part: tooltip" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_long", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported hyperlink part: tooltip", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "image_one_cell": { + "write": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "error": "unsupported payload part: pictures" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_one_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: pictures", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "write": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "error": "unsupported payload part: pictures" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_two_cell_offset", + "sheet": null, + "cell": null + }, + "adapter_message": "RuntimeError: unsupported payload part: pictures", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "pivot_tables", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "comments", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "comment_legacy": { + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "freeze_b2": { + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "error": "unsupported pane part: top_left_cell" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": null + }, + "adapter_message": "RuntimeError: unsupported pane part: top_left_cell", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "error": "unsupported pane part: top_left_cell" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": null + }, + "adapter_message": "RuntimeError: unsupported pane part: top_left_cell", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "error": "unsupported pane part: top_left_cell" + }, + "notes": "Write failed: RuntimeError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": null + }, + "adapter_message": "RuntimeError: unsupported pane part: top_left_cell", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "nr_simple_cell": { + "write": { + "passed": true, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "write": { + "passed": true, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "write": { + "passed": true, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "write": { + "passed": true, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "write": { + "passed": true, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "write": { + "passed": true, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 1 + }, + "test_cases": { + "tbl_basic": { + "write": { + "passed": true, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": false, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 0 + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_with_totals", + "sheet": "tables", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': True, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 1}}, actual={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': False, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 0}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "write": { + "passed": true, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "write": { + "passed": true, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "write": { + "passed": true, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "write": { + "passed": true, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "prot_basic": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "zavora-xlsx does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": null + }, + "adapter_message": "NotImplementedError: zavora-xlsx does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "zavora-xlsx does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": null + }, + "adapter_message": "NotImplementedError: zavora-xlsx does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "zavora-xlsx does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": null + }, + "adapter_message": "NotImplementedError: zavora-xlsx does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "page_setup_landscape": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "zavora-xlsx does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": null + }, + "adapter_message": "NotImplementedError: zavora-xlsx does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "zavora-xlsx does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": null + }, + "adapter_message": "NotImplementedError: zavora-xlsx does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "zavora-xlsx does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": null + }, + "adapter_message": "NotImplementedError: zavora-xlsx does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "zavora-xlsx", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "chart_bar": { + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "zavora-xlsx does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: zavora-xlsx does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "zavora-xlsx does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_line", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: zavora-xlsx does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + } + ] +} \ No newline at end of file diff --git a/results-2026-09-08/mutation/README.md b/results-2026-09-08/mutation/README.md new file mode 100644 index 0000000..5a33b0a --- /dev/null +++ b/results-2026-09-08/mutation/README.md @@ -0,0 +1,19 @@ +# ExcelBench Mutation Results + +*Generated: 2026-09-08T05:42:21Z* +*Template SHA-256: 74de96e1ea2b6ee8d52e9ff13b51db36d9140b371194afa1b70bba7158feca5b* +*Repeats: 3* + +## Comparison + +| Engine | Wall ms | Peak RSS KB | Preservation score | Lost parts | Verdict | +|--------|---------|-------------|--------------------|------------|---------| +| aspose-cells-foss | 770.000 | 170848.000 | 60.000 | 3 | Loss detected | +| openpyxl | 750.000 | 170336.000 | 60.000 | 3 | Loss detected | +| wolfxl | 780.000 | 175696.000 | 100.000 | 0 | Preserved | +| zavora-xlsx | 1320.000 | 169568.000 | 0.000 | 1 | Mutation integrity failed | + +## Notes + +Wall time and peak RSS are measured in isolated subprocesses with macOS `/usr/bin/time -l`. +Preservation compares each output package against the original template. It does not measure formula recalculation or rendering. diff --git a/results-2026-09-08/mutation/aspose-cells-foss/repeat-1-input.xlsx b/results-2026-09-08/mutation/aspose-cells-foss/repeat-1-input.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7 GIT binary patch literal 15042 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/aspose-cells-foss/repeat-1-output.xlsx b/results-2026-09-08/mutation/aspose-cells-foss/repeat-1-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c13a0dc0f4c56292757275b5746e96d4918ea380 GIT binary patch literal 14832 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/aspose-cells-foss/repeat-2-output.xlsx b/results-2026-09-08/mutation/aspose-cells-foss/repeat-2-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..70e1d2cfc952af8e7ca37f941ac3870d3a0aed71 GIT binary patch literal 14832 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 literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/aspose-cells-foss/repeat-3-input.xlsx b/results-2026-09-08/mutation/aspose-cells-foss/repeat-3-input.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7 GIT binary patch literal 15042 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/aspose-cells-foss/repeat-3-output.xlsx b/results-2026-09-08/mutation/aspose-cells-foss/repeat-3-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..70e1d2cfc952af8e7ca37f941ac3870d3a0aed71 GIT binary patch literal 14832 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 literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/openpyxl/repeat-1-input.xlsx b/results-2026-09-08/mutation/openpyxl/repeat-1-input.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7 GIT binary patch literal 15042 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/openpyxl/repeat-1-output.xlsx b/results-2026-09-08/mutation/openpyxl/repeat-1-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..12adfd35232a77c538a00b509e08ed4b7578d8ed GIT binary patch literal 14099 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 literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/openpyxl/repeat-2-input.xlsx b/results-2026-09-08/mutation/openpyxl/repeat-2-input.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7 GIT binary patch literal 15042 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/openpyxl/repeat-2-output.xlsx b/results-2026-09-08/mutation/openpyxl/repeat-2-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..06498fbc40a730d325ad98c637605a7cbc1c3b8f GIT binary patch literal 14100 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/openpyxl/repeat-3-output.xlsx b/results-2026-09-08/mutation/openpyxl/repeat-3-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ed09842cb3d7452697e478331e20e3f9e10e6fef GIT binary patch literal 14100 zcmaKT1y~%-5-lFw-3c1pU4v@~?(XjH5FCQL1b24`?(Ps+EWtIn%iARP{ldHV?YFbD zGhf%4sp^{Us#DYQ(%=y2ARr*nAYu)a+G2yU5{ba0ao~mw+>C4uf=txd@&X#8-)2e@D4K7kX5g~YQuJxkdCnk8#u^&y<`*ZYSrp}W| z?_F!TKT`DmP-Eq;p(H9>!G}fO^&sbuK$GT5rh$BkP#ncj%-R{TeKdmXeA9|0|1T95 zC|C1ufwxWr1_FZePZbPp9gKhJFdo+})yIe&tSjnZOF4d!n*)gWAt_Y-#SL!w$fnv{ zn0e*|kUp?lnTtfc6_+Zo?gd`bkn90{iw^bKpLQT(*x5T_+4fu3khEX%&7KmiV(y3W zW8{onCj_2Tsm?NjfDJDML`fV`SQEYPSZ^&Y@(K`(&7j40p*0(z=^D`mYImrID0_q|oH%(t+k3VXk=x81St3yPTbpb6dUB*Db9{OnuKs1C)=9N3qia8Fd-_w zyT|E%aYApf7aW>!?xwfI09a^iVp!WyWhO%rV#Fz`I_-ijkkM(-FbC=7^d3e-?Oh3o zfR=VcA6?Me(8OgRT{x%*tf~Z=TjgMj8|iuL(3%NODSgzi)g`XqCStk87*&cg&I3hL z6{2Vftv|oB>VI5b<2Rn%=O$qGw_(InBlexJE!vXP2>q_q)7NETDxhLHI6Wib7clId z0NE;eoi~dC&5XdqovAkA;&t73oEQ%BGwS z%_%6KDlPN(G0onKZ611{Vl-?E&Ju&D*|{u?&44HAyt{W!z+EC}TNTneRXgDdLwO$P zhgdM5!AW8jbI6Q=LCHW1nc!<)23mC7mOdH(=(x9)T@=44`+maiD=o~~1F5Ed2&D}Vngch!>3grq z>+9G8a^}gOcd&#QP!mjDfQJOK_$C^(sn0=0z8 zM^*yunWkX*Ib&AvG=YKaUMlvpc^zqy6UF!*3vRbq6`pg5*$l78Gvr+c8!Ub-9s!ss zUY!_8ka^oFVHH_)T15{E&3k?W9CloX22B4(`;s6%4b*{YH@TU5lt=Y)ws?NMp`-Cw z=ZS?_M3guk4q)4fh!~Vk!eCCRwBuZRHHfDyonFcAy?{}Zr)Hnvc@`_$=o|4lEU7Id ziXwr1X4W@(Y3eZTK`Iv6r6H{R#e~eTkY_D~{M#OGupCJPU*#(UJV9TkmpOXMZUefw zeCfR>3x2j-^5x7lagchOcF#s=u8G-b_B~WGEibatQyHo{j1LVeRmH#i#+BW5^kl}L zb#{EeL>5$)rcOtS86)jqCq&l#7%_56-3PO0q)84lsx)iN5ssSm9?xc9@k%Ojal5L8 zs+m`FYriVTiJx}zj#qcLejJWPxXD5KpfRDNfr3-&vS!Rqj&Ky7$CNjYpwaaU0o%j1 zw#yc20i$BFa5L`v4sh$%%oT3Vtd!Um*ja@b+upnVemC47TuTrw-YKfqyWgg#A9lMx zR_FcXO(GZ!J=h1i_tZ@>O&pMCMYpypC!-Z>(raEkqeb5^(xdzGCa~%w z*tvqT9+Tz(I898hmrSJSp51P;mhR?s+$NyVxWT6Cohy#@TLrEj^At4GvXM38nr>x+ zNoCFR>JAIOdJMVAXZ4DqY&N{ za*EBUE{#ZF%q?wPB_761riJJ0bnq~=nxX2bKV-F!=XcXHDm~u1+$Xzs>zzN@4T~df z^X%$gY71BTT(554+r;xo$Yi+pqkuYzf{`ZTLt$buZ^@s;#XzBfjwcL@oPq@y72^A) z+{3k>!?(P{n5f|A@)e~G43^WGAxA|IuZD*t!E)IA`7_?aHFEKu*55iviP>l#YeYD# zn~%jo_?r^>MddOD+$X>frSUf04hlW#UJsj0I?5M-&KzGo7N6KfUg`#6U5I14M{|#8 z`HR{D;T`ijmmPq64P0jjjaE3{r`tO`+z+M9prf_w!yS1BPrc`vKXLlw0wDi-bpzgO zu1urAhz3PK`i&P+9F$?C<|V7{XLN&#!kUVKWhQucKeY?^923s<5YaSTmidTst|(Yr zp?Se=0l*xB*);+yek`O8Q)(l7-j*CJ@5=K}gzBEY=^$ zT$Tv8nA#t8GPWgSy+0DpN_o=~nI=2Fo7JA(OPRd&IvI~PcS&1YXB+KEym9SUOf;pu ztH{vGiXN=@(jNZWOkZSm-?-sSLTtu)QCLQ6%~9 zW^~{5`kj3m)HuiU$kr9}t*64z5#f)Ir2<|{bVV2DPqUOMJ#7j)+`4Yx>&q?&}}7rmH=O4+aR(g zZiV`hhmcX}e=!YZv)J`y23}>k;a%^)&UPxWOuUB+A^Wp&b^6jcL1q6*TV0FN_{sXp z@``BO&n)D@AuaPD@LXJ(I<3TI-dm|OM{#YO`bzUEZmH3-skZ5Xa<(33-Mp90I@fg> zS~mTP#~NQYeVoTyOE&#BlRc|Y_FN8+2r#DPyUHE4&K-r9=F63tT{^6#`j}WUz9``9 z^V|~s{PE4*-4*$wvlgIH?sV6asWY7q$j)20nMttSQ|30e=4vdCUjWd(G7=4WZJgwK{>PG6N_R@PdR`LQkk@z%2#Ivji7X^p)a1@wq@W2V0WO+IF z5RA`kjn9sar?+25nxaCcnxZa;nyzk_n~raxs9*pj&I6i>AZ-2Cb~Ms@3=vhpU+G51 zYJwjh_3#c3yB0RnyBar{rtI^{g%8rsUF>N_dvuZnRg*r^5%qks<`seKWm-!z*2g}u zR>uq`v>mNwJaW@aBDsrVg0TEDh9m}GA6y`Xrfb{xPCwH+zwzf+`2WNRBhi>72niqV`=CVd_few zI3mj~BR?yU2eJgvH+=!13^Fxi9!MrGC?*;xCL4)lsi1Igd;PTI#{KxXeS*JH?!&tY z1z|I$NiYM4|Oz)!rBLyHnn#m5+CbmD0Wjgc2qi6Upm&MZZ4KyUtczb?8%xJ z!udsbh$CM@m1Lb&tQ9tA2T!pz*~FyDq_DvR%0XHY7e3LAMelRrCGs05c>mf-a~W{c zzN}a{L-`x9@gu15dZ=;1Ky&%PQPdD9897nQt}V`G5EI9=xvpV#GNF@{+_W3|@nib& zdiwG1U`Zu#moRDYYv5jI>Yd=Jo5MC1DJ4Y`v8$~9xM${$OXiM7=8g&pV#~Z6sg1&N zr3id5435}P*x2CE@B;Y|pQ6@9_hYSgNsCVaPJT)so1TL@Iw-~N5u2We)G{$;h(hE_ z4%$c;pQ7G{PFag~S&K>;S11#VRoB)CF&KVK7u49^3bTX5`>5D>Mwyt0!oHn$4aYVO z#|n*$oG;vDHK3j%6`%|f2H+-6r8rzLz1S_{N4V~KkwfdU?zmn2 zTTsfw54UEBD@yrmH7%<(Eekbw@=C*rK&R8P5cB)4QA>kr$NerULuux1w zx!uIE&BU?7#PQTDZJBsPq>d|`Im#McpF7UaleN+RjYvJ$L>8W58VmUShDwM`}l zB53@DCq#;ld`0XmjO7-Yqrn#01?t9%Tb}%7Dcw=&cta^&SAnDrIAW*;T!Jy`%Fuov zn?p7PhaEp+b4r8Y*nq6D_HUI5z~jp75hIM*fSSOWw%!`>3^zE157BP=^h|9b}?OcF*SBE ziRW2cKbD3$krufU_3x3ODv-yR7@#mYILO8jbFBHJw>!bLIl)ypMdUQ1s=`3ZF`yla z$^8_1TQm#k;%X7bCv^>TCgoTQL2q}4YjcLHaE43yQusYeL$)4|s~s&YW5Nz@&LnNE zYj~I(ls=M!G*hRIpv?uY!i9%XTy_Q^R7J5Cm9Z8rB1hRmaA^{^Hst+dwd>PabpEVo zli`hx_~B}_a~ikPkpThMfcZ|PRGzqkL}KKR6=fLCr4ESZFRtXKfrA@O{pQK@3^Mud z57EMjnS|?Wk!oiV?WVDlcjy z^>N#i!X9aIE({M%STYA#hFRzJ>F+%r^4ZJoj?cKmzf$>H&1xYo&T73|kyzbo*~7)J z+wqR?Mr{z%bT6&Fr_7r5;&R^2v&ElHJ~0l+%}Dr+WWlqW-lgeA)9O~I1Bs}96gI!C z+up8c2dD(_kJoRvcLGY5UlMmx?{#ZNjWl^POI==&+pk1suKTtes473IXXO3xC>>p< zH48phb#KZ4eBNlMog~Vom9pb*uf4s$ulg|Otr)=DrsTa|{jg8ef7MjwkjzKmD_uL- zd%2(}bBth>@Jk@*mSwAalGHt#Y^!@#eUjUpC63VQ(;__oms=;Sl;);_sjtdih& z7~v&&CeL2-9TX~KRz5C~Yq)w@M=0Au;s$1#wv>Gk?{!*w4)}$4-^Aabo7?)x^>q?6 zBW8YWR8TsecCC#K$dFW1rx~cgulA|1atjx#9wx25?c?n<%;-m-8KH#i51{USe*VyK zC6V9xZ|&fV%Z;#sR8~6#2ng|?Fx$vM-__j4^e^okMgE*%qIa>jN>q}y1u()t(FD6# z;{u+rOZz~B5!em-DbBXKzoewE3cJGh?tCpNH|m!h*a)MNRlVbTjKmJ0D;nbZk%pyBYOM ztY~?3tMY0pJ;}HUUsc$Fux4J z3W;RnNupRaFQN=X;)Yrog=NkTh!D9)r<7W|{|-VM(dHFIf$I{l@H>~YeTZV#kK%|p z!%_`SM(pr)<;qXE$9-Ml+vBUo?z3mKODWvyT2Q@+Y#g=C9Vfx+;LSE_J{=c_i!d4p zfwU%?PR$~LUy~6m5LAq4SPLnH+igv@iKudScssi2%-26JGiFX5gn#`is{#K|$0T&e z(R&%1SE!vd!w^-fD&? zN56yH6p~Wi-)3iR?04)&uTWZ??1>h1K2MbSnIK%`Ej*jsnlEj(H(ckSO(z-=>wQ$? zY3RyIAQL^zMRM{>%W=fdyYAj5H~9e}r61GmVvqT&xuMb3k#wGt^)9jEj`z|6gXU{% zpgsgA6$1bED#ZEER4~Bj#R%wGzu4bj?4Q1Ym9gWW-S6kcI@VjRml3|dN?{u$|FG3Y z#*$o#)gMBFksetkS!^U3HMs^5-#|J==ezT?R!86&cqA;?lO8uFk(&|}H@A#yjnk9I z%*P$ax`NXk&0uelLpQu?^%U~}OHd7Ul+Hibs>+G}l=QwO&MDMHwglixoZ2=Gl|Wh1 z7?6Y3w_NMA1xuu^<+Sv6+|xHlQHuLZ$D1Ty z|MpPCq@%@i4|Vsh3%@$-3Gl4J)3+PE!4ZB~Okd%fL%%C`jiMF4Bs;kLJf(W<*YI}f zcyoq>yEdvB*DOcWxWbJePcA8b9HuS#+`&`7;)loX87C$#Kier(O7w5j<$o()Is%$( z0cbkXKc@Rf-mB|iZ1vCVm;TprLmZziaO4Sok=n|{XLKrtMkBy(ReJO@WvBwh>uW|8{%?Pbrlf(;2a3NC~qL41W`yDvEHbo8Fb9p$LgEX_A;*P>+dJSr4 zyD#8_T~zfBITUTo{5oV&JlR}jbK(qrgca1$&IPw>w&=7wbhp;~+wkoKx#D&2SkB(n zYRi*#PP9uoCNmKrp=Iy(ILN7*B1H-eG&z=eK4@eN3LzmzsBZ&80$Al!2FA9&P)N=Y_cN@`u5K&!lBblx8gPWCpv5Df#;_edaGD* ztB^*NicqFM-N(g|+FKwhUCQDU=r{$3G1d7P9!tCCCNOklm$d@0DJRks&0QYQ_^?(f z7p646a@AgI*)dsVk5`(T+wW0k(m0x{XSvglEPtzf_~zZFT?bb+lD5_qapJ&_b?hlZ zbKS@kdWLeV!k^s?p8{}J-M%KSiR(m?LFi}S>_2pqi4 zF#Cy#CzAeH_ioXnZ?#1ACpSeH7}cC=v$F;zG~DG(<#*~n$LouEhlL2~L&A?$VK2tg zj&phZzGl)7<>9n^7zC>|2b1SrAMi*SG2eL5(qp^~tT}j$C-9_whSRZHr1R9QpV@M0 zPeyXE?M`eMdjz)?{fdrvb{yC&6(TK)<(km6?PKj=k9jw;qFW^PZEig@crE8rL3ohL z+Hwz~fB+#gx4tZgCE=RYDSC!KUp6+B32zkmZLw10Zi>~~Xns=Qz*>7khY=k-zE=jR zvH%0ApA}~EGvG@Ap_&$c=cmAz07^A0%;k5E2VGn*o_Jj@wb~zXBiB+0})NhN%$SxKORO-j8kaCDPR^w4uvy)!zzdcVuF&B==&ok)H}NYbk4eW zQ%`K-(QyIFMx-YM{ZAGl@-=x9y8Y0JoZ-jH0rDkzW;zAXiCp39%E9t2d7;|dP3VjV z(PFFWd95#Qv2c+FO-qnsHI_$UdEcI#{XZW4XzikMG1S&WZ!4u|JBoAHRUCqSu*JtrqFdSA~$qkO>#9mg&w{hZx0>DQ)lnqER50PB#-;pe*gD zVW4jVV;5mx(<9k}olKQcA7Nk8BiW9f{4V1%!oHH|v0&S1V$xCq+M9gRWJ&@a`PHvk1^~bo>;TicaPpCd{*8>L!(AQ(q)gxZ&RnJELOt3 z&{$}AxMIyg-=-LQ3i^V9Ql#vxk#<})Io~yb7bvA;*0e#fZV}aM7p)G6=n9A1Gyt=t zkCcWkZ)Kz>uRiH%j_ewN+jIc4WI*7+W>0KfYG@n2ZOG%eyzZ!dg5w*a(4oXjUfeU( ze&V4wy*ZY?zDy<#HdA-4PaJQp^ksv;xCw52>(3xu-E5bXgi&-n6}&pzY9`H2%UJK~ zTHcy*2r3W?ZdWQ6tUNEF*unhld8YKydBQF7Ft>MU@a(qLuwogcgJ#*Zraw1V9Ho)} zE?3YxWMPwWqkMlCVSMuWOe7-kk?=5{CfW4SkeDai(A4t*>E9E^m#>PnNWd|W5m;vX zA4Dn3?=kS3reiuMw%_;89*3Ib{*YV21x7{W_nAu*`B#LMVJPg1g5@!rF1}B&)nRv! z=6gp3J)c23Ez&|)MTcz1!yJvh86ry0j^Y)r>NZ(J&=}%(0*l=X1crlX(F#J&_gEXY zB$s8W;Y^v*D>9jfX#nfayE^%uXr{_r7{0M8j`X7<&(Llp^jUmOwv-(^gYgz0IG-!! zqP-^Pv#%oNNKKoi(vrVgIDAx(GtGLke;(Ue4U&6IypVQuwQA7aRt~j2-cUSPVrgr4 z>aY0u&^pwXt}d{KlvwP$n+ogx(aoj0x?=0gImdIZsoQm#yi~%f@PW8W*vu~TyXS3X zS6>~wsH?#F%!TCEnP=Q5Hi5?V>+Hik!`b`vdZe>Xisv!9Op?i`GdjFu73HcK%b8Po zbl=?)ZujejMujZ$-S^%YSOZlw4Y(umBIM6<;SuD3xaX58!up#9`l{u`b()gN-FvZ- z^&1)+?;WX~kj%Wxy!vd;ki)Sq){9a6>70)Y$g+_hVS7Wx*~qd{9-sEU6)%RGh_&Nb zidXekV@K#SVWLGa_0B*YKaQ;*WNw>pGc5DP4JzdF2HBnuR_r(Ry= z2jRt{lFDzNEl(j@E6*zZK5>%zp=5~qiE`%oeaz_h>*qA|t9iqI(2CnyS=eguQUggd zlCOxJJ zY`r7@s8*YhNQe8^~AEqE;}J9y6PJu&xHk}94= z*NAOr{WY$v#ZT_`;#w(KuCZ_zKcZV18BPqacKQh%_1E5TjPPW)|D-cf^w)MWWD5L* z<)#lU3{HlO3LZ%u2_N%b0)a7@kzEjq#4~7f!qv06L{{qo&EF}jcS2ftm+L4}7>tCe z3%X|r@JXh4I+P~f&cmQJ7_;nShwgUMjy~6zXf4|u`=w2 zEzmdQ(9{)*ROuG@ZkEpf%sMPuTf;21KVSJ6t@~Iq_&J88UOuD3UO!MN(mT+8LrM*k z(2GIKA^**&0rhu39=$-9H0MkF?#aabYgZ+KMbh{$Rb+qtQJCX9ED?Q77}QD(ZE!GmmYAQ_Nf*X6VIBlFzHs7GoRKPy#TtcL5swKOz2K z#{LuF|I_5ZL;U_2KG;A(;5F zh={6M&fhb?$v(!f(^&oC2&Y1pg;LjeM1@6CyN-z#N4jK?#u(Qz-KUnk4Ktess$FMV z`W@vC%Ye~j!3*a8k5qJ&?#=k4tFjI9cRe7)U%Yu>dU3|q?VPzzZM-lDmh`olgU3Z z!v0|GIpD>r7bC7HGuihN`q8rJ7I*%DYmSIcAWAm<>E=q@54AqljB6V;KGofH&3!{J*9gvR%|Sw~Y$#~% z!*K=ET?}%jl{(aY-AHPEs**m`K*x_@`JiBz)m#{U24HZLq>;YaReooQ*ab zrVeD`7VqHWP|bt{>D~9KD9oXGY#U^!)!Bvknw^5Y4QS*mxOhqrE4Va)235z5V%kzH zJbtrp^SSBsW0)TgR}to*bk%Xi&AoKFzrL`Zi1h^zk?dyfJ1~*hf+04f2CPAGXuzDv zqAjk=UiYF_YmR!m=%3m+E#fVUH?evYlj!Jc`ViysEZr*XVDzE!3@%jY9WLmnvtj`H zhAC9_4wb8~4yt9-!>tdDW@)PVl&bmW^wZfe0As@@s(PN~z;7?REp=l{{CHK@LY3a( zqP`|jwr3bqRS!?88sVUt4k){CG^$~RH{@$)A!WGQ(di&~_9@9f!j*`)=pnj+k(!>I z8&qGYnZcjMyvvSUn1Aye2X=j14WeIaKjxaF5Z;ISaUgz`WrM!2Aa1Ov`H?E|%Z!Io z1{a3qSzKXSs^d$6C01V%_*W(mf z+aG`YEYU*~+?wkPE9&}D4mCif9VrY=3!eu!ef9L`q6^rkFJcB*+X>R;ZaV~>EJ$zg z8PvcJn$W?PM^NeK6g?}Pxrs#}Ez|t&NffDN$l_A`*sHMPk-sCM+4o3R&F-VA<{o?6 zT=9*w7MTotA*oki^I?}8HESC9bb&m74~0lEL(`;wTBoiYLOn*E*>esnq~)?|3Ay&Q zmZd?ztGtR<3St*(V;zehXZacRja_ouVWfcYE#&&9%#=NUH1;+-8-+%vzd%DG6be{y zBaWyn8>WeSzF`wtF#6{;Yv+QqM6nL6J6Br(8R*LDYGf-Rlco`oBfHWxIF@QE3N;^S z1HG5@M25M+As~KLe_(vTCC6o0>YP_uLP*>53P9p10Gcu!VeP=)4ESzst4FwM;P-(4 z1HJH?qc%1%YQk7f2!B{HV-~+-@Pl(ZDz!&TcK) zZcX)j20Q0rKUYKTJ|riR6em%s-2`sN)sGDIr6aJ6&*T}Ol{t42COqsXDy)1!CwyQ` zJ7IToyVV&cJ|)so+rPhNp?&Ue)f_%+0}zYf5IC+d@+=mE$S7F(LPx?Pq)EmOqETd# zI2t2L#?Tdv^sb1Z-X`2m1dP|=^uB{9eW6GHqGXYhskTk?j4B#_Fbf5{Xi{bMtZ}kC z^qz;pxx!^7^%HOuy2`Ic445K4dUo{M1QSgAUc98%)`LCkKUR%{?~akgbO zytoMV!tn3;UTQF1BNga(@^By^2!B{6M<;h6LH8?DSXJqcPG>}Z!svUG078eLJd{%$ zOWiOp)fS>7%h(rJQ^G_uQ&lxc5o5($=JJ^w_S?myNtWpVNt;kMmpAXn(!i2U1FD|* zg{LAa+-S<>*zcJ~C5#fJ%Hs8@rR=yKqLO?dC7T~>myAA&r$FEEFu8=tA$5O@evkE? zBJ#RTEPOsLXhJV3E*few2uoj*vkbk?QgZNiDHV+opFEj*N(`2+2b;Fn_RXLT6t$@U z0h)q8lLN|1ds=eUnvy1td3s=bpPoRs0CL|6 z?b}uJqb%YJF3zINSRGoKCG`oj>B{1)HQm@_#W>K36_VT>)feqJ^w~iMXQtTTu6wo5V(&XytcS}Bck^-~^-NMQ#9|*fS z5idyn^z9iTu?K6aIbUXd8uxtggUtaRv2-I#x%h+UBn3};_Kz7WTF;p~?rA1CNgrM7 zPtX(8)@tE9d~8$L_4MqCXF9iWtJv2_s%}74W*5030PohqzR8_wf&ZAqV?1BcwWdX6 ztftm$2S0nV|5Egr!TPDxV7VGClGHt#WGdpBaGaTp2gmF2s#{JnZKs6@bgYV4mI*?R zG+GZ<5Ii`)#G9+bjYu^4MydWeWbNfu#E~4{hTjGBT{NH{1Kk+pPw4bJvdD~Uu>o?+ zK)!D(i}B4ANhpi)879OXs7fx?dRe zbB+0CP>DwJ&*l@c?aPmhS;PcMwnwa{lC zm(iz^r#RX_q@l=*z$@Inmr2&vhtNa+sQ$BO4;0*Hnpj}FG#gJoRx|`NJ7-KeH&^~) zwT05_I=W#AeJg5s-b<|+)PQ!afFpCrvK_%Y`06?tlca@P5<-mx^2GJhiw>7akR9pc z=<^#~DDGK!f#D{E);2^^<-T}k5268kMy9-%nrT%GOuLd*#l=1 zf0~W@sr>#E;)pb8d-U~@;)f_oq2ps+LiqSVhPt11tm&DPJHv0YG9K`@dZa%{T^uzh zO`tIqN?VCF4C5ULxHo+sSn6fV*#uY`fq$oC#@JfJ)Sswxow{}Y?$D^FIEUbES)luQ zcYVvYejr2YWJKFdJK9>nXK5Sm-(A~gb#T-Q>{48C;P$6$|G4o#JNQoq5YL4e$cQXj z72pLDOfHE6s*JlF3a7?MYf!VDN@e$eOx2|j&Kf#$Z+Q2l8ktAw5{JhoziQ?%(1AyV z$yV0^F0W(AFszIla#yHSn9M7#=%3_HLle|>VWW2qA1mTn7%z+aLQ-05<=|EPIKSB? z&~>U(Sb!V*DPB^MWDsn?1`mxkDO6Y_^tV~u`Qs+z zDo@*89$D)@7CQQz%@~HS4nY=FCHViXaTQnhv^CI~o8J6+F*6fYqCF`StTjd`SeLGK*_|8zjYDp_CZ zgWrSu!@^g*PfNKmU=B1cX$s6Ex*k3;CTO7Ro~JrHG3Cujx?1u0Jk-J8^Fivaaog1Q zcu(=A{k|xxM6ioHgy0XoFV1ENyi1h9i&3fk>MTL`Jx8GOjMwA?K8!z7t#<_0TS=rf zqQ1rDX}mC3TQp*ZEpO*QNEpQR0A9 zEl`=ilK%e-C-RR%`)jnMfHNxx4;@=3QSg&pKU+avo0bf_&{sQ!u z2NKah1z#KccRKSLxvz0v&s~4xfHQ)C{Fj+bUK$d(2I^O8j}D>@q*im7ejWWE;5-A$ literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/results.json b/results-2026-09-08/mutation/results.json new file mode 100644 index 0000000..7e825a9 --- /dev/null +++ b/results-2026-09-08/mutation/results.json @@ -0,0 +1,743 @@ +{ + "engines": { + "aspose-cells-foss": { + "available": true, + "details": { + "added_parts": [ + "xl/sharedStrings.xml" + ], + "customXml_identical": false, + "dangling_rels": [], + "element_diffs": [ + { + "element": "tableParts", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "tableParts", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "tableParts", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + } + ], + "lost_parts": [ + "customXml/_rels/item1.xml.rels", + "customXml/item1.xml", + "customXml/itemProps1.xml" + ], + "missing_content_types": [], + "mutations_landed": true + }, + "peak_rss_kb_median": 170848.0, + "preservation_score": 60.0, + "status": "passed", + "wall_ms_median": 770.0 + }, + "openpyxl": { + "available": true, + "details": { + "added_parts": [], + "customXml_identical": false, + "dangling_rels": [], + "element_diffs": [ + { + "element": "tableParts", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "tableParts", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "tableParts", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + } + ], + "lost_parts": [ + "customXml/_rels/item1.xml.rels", + "customXml/item1.xml", + "customXml/itemProps1.xml" + ], + "missing_content_types": [], + "mutations_landed": true + }, + "peak_rss_kb_median": 170336.0, + "preservation_score": 60.0, + "status": "passed", + "wall_ms_median": 750.0 + }, + "wolfxl": { + "available": true, + "details": { + "added_parts": [ + "xl/calcChain.xml" + ], + "customXml_identical": true, + "dangling_rels": [], + "element_diffs": [ + { + "element": "tableParts", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "tableParts", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "tableParts", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + } + ], + "lost_parts": [], + "missing_content_types": [], + "mutations_landed": true + }, + "peak_rss_kb_median": 175696.0, + "preservation_score": 100.0, + "status": "passed", + "wall_ms_median": 780.0 + }, + "zavora-xlsx": { + "available": true, + "details": { + "added_parts": [ + "xl/sharedStrings.xml" + ], + "customXml_identical": true, + "dangling_rels": [], + "element_diffs": [ + { + "element": "tableParts", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": false + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": false + }, + { + "element": "pane", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet1.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "tableParts", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet2.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "tableParts", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "sheetProtection", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "dataValidations", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "conditionalFormatting", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": false, + "present_in_output": false + }, + { + "element": "pageSetup", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "headerFooter", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "sheetPr", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "pane", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + }, + { + "element": "drawing", + "part": "xl/worksheets/sheet3.xml", + "present_in_original": true, + "present_in_output": true + } + ], + "integrity_failure": "mutated cell values did not match requested values", + "lost_parts": [ + "xl/worksheets/_rels/sheet3.xml.rels" + ], + "missing_content_types": [], + "mutations_landed": false + }, + "peak_rss_kb_median": 169568.0, + "preservation_score": 0.0, + "status": "integrity-failed", + "wall_ms_median": 1320.0 + } + }, + "metadata": { + "platform": "Darwin", + "repeats": 3, + "template_sha256": "74de96e1ea2b6ee8d52e9ff13b51db36d9140b371194afa1b70bba7158feca5b", + "timestamp": "2026-09-08T05:42:21Z" + } +} diff --git a/results-2026-09-08/mutation/wolfxl/repeat-1-input.xlsx b/results-2026-09-08/mutation/wolfxl/repeat-1-input.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7 GIT binary patch literal 15042 zcmaKT1wb9kvMuiJ!JXjl4#73JJHg%E3GTrqI0Schch`*tO>hYsP!)S;<2#9~1<{33!MOJfkgYXX|Wg>#VQhVQ=cB z%iwNfJ)p*~(8q+bevkP+8R@M9HJV5XJ$SVUG?dy>3!B;w^8Fg}Gr!qKl{_JlPttS_ z_?sQK-e=CEKYXhWP2iCVXX<8D1qdlVhfo*jO^D;^e`w18c|Y*udL4`sqs$>$Z3DnN zsHpOpYkx4XC~=l+fZt|4LX%<98`7GEaFfZf9{Plph-voz2dZ>usn2D7@l-sgi=uHl zA6r0xRkEX%6?Jp5Q{%z_s?5zuobrdL9%-%i0)I9`L8bnD{Wm;lOHB;BepQl`P9+#nCliP3fQ#0+tY-ybx2}%8sc-kNmMUK;2aj5WnTpbSZk( zqNX1#7=WS{CB}y9P(KJ`bZF`jPc?@_JiRBW=gBF|MF+fL%9W6Pelg-B*qs| z=L;XM+BC4SdM^!fWQOy`i`d7PK*q{J}VM_k7cNvZ^#~n@=gJ9 zuwo(u-8#*Dz`}A$zw~k4u?*}B;g#Io+Y+N6>t3-rb?sUTt_EH(GoQ<9Sr}QMaTq} zDRwu!bsaV0dQ12$(qF_3SE(3{h3^CYoU~<4B?_-{VS(a?^Pt@?prAO((YkGzFEiO6 z&mvewMHe@pP@sro@KrP&$%MG`r@0D1B}O4UZRXNFe=`S~60BI5$TeYODoMVJro(yi zPH?o88ErLVC{q8^hIB8=^5qImOV~=66_PutONE9DbV%_fqP>YCuchw4I695 zzk18U+0=&lm-YYdw&+-X_+BQI(A(#T9oLLS;dioaVbgL2fmV`LHr4mUQerP1!r1Ug zF>Yt;SLdfkAG5dQ1>Rb5C3^%2iLc711?&{^S2k*>uRO~phJ7cG8ikY;q_oF3cIF)n z#FvVU)0Uv5=(yJEXL|_XCb2UjZe)l+yxK%4XYq%`N{`96YeiEAn-(B=%CGjRA}1)% zWKX;6>)*xCTTtiEYM0wa*1ZcLmB5thS~AUU9#&Fq{HE3MO5MHX;LaeRnoYp%*EIj5 z?%#^4M$5tV5n}}3W{a%hW$2=^w`CIZ3x!RoxU0UOO9wQ?Jx}j>d$Z<;x{7*!)bU10 zzg`c240D>~ZQ zJN+IZ-Iy`BASM*CTVJtZ0r8U{QgKctdu^?69R2UXDdWkLMZR~rNw>Y_&oDgg&QfM~ zV@<@n`<#WzrobxQO|xXh3+KsAv=YGKqI8{mY??&EgRBc7$~4W@rZz3{9D)f0AhwRI zUPo3)M+xkr!-5np#z{%I`b^2hQeX=jIn?7pMpo&&Yl~AKxLCU2AKgA&%dbugms*x) z5p82vs?Y-)+C7u-VztQlPvyji@LK>-Uf*;OKAOvkaJcjY|7{W;@8&kzD7o4HISi@4SDyr=Bj)?nkQ zp&}|=Cp@n>jR35`r&fXujdo+RUf^NnBrwW+lSxUFSTc-uO8Pxw) z!Pw5x^p_432|d#Nz*(a&=4eNCvi&7DBXV0xxcaj@{K&CwwS_3l>?t5)aJ@1QnRquL zO>om2+@c=a6Xp&BDmH*_FmlAj2V>Q4IeQr1zvT9t3Y~JE!o&$mW}Y)5@40kW8G*>e zJuZF%O9aMvcQ4~RO1%6Kq!M!&iS`-z4ZmQ9z9^{UX+s6nFSTHl2jS05E{K_+tWiwO zcd9~lC{EW3)~6u6l*Q&L^IS1|&7&>#qL5Xw$WtEcy*KeHRm>d`YSTSCp;?q&<+f+5 zUX)gPRq%R+bB+v`9vQlRcUd9p2FHuf;5!+C`c02Y^XhpIw%%w-h>s80m+1fOr8eus z<5pnr;DQ4;;NJazJdB&2qm_}Joz>q?W+0Ip>6aZ>1$u*oQb?hKs^YGO!D}$l8P)8i zy|w>|^0r$kf-P+H!TA13Ju08dH35%ZaoyZ;uoLes7JFSMxT2mh$q4u=b?U}u~z1Z3BV$L{neFU4Dw9i%{Lq+HOhvA=M_#W znD66IvaB_s9_mKZ>eEyVp$0p*LluKJb!=ILJ+mhL@32m|F3s@Y*h17vph^rU+Ti!t zSA6>k*XK|2*cXP-Y>mD|^Rmg%IRdvXtohI?0!YReeKy>#@@j(RzleI9f8) z2Fmu1V5uA6sZ=8#R?`DzznhF{S>p}+*;`5*uXlDi3SERG2SmCN5f}fAX<(vZpx^;D z6mDh=V72JBrw|p`xqJh+xu*d!ApJe=hO-F4m*#OWah-LGp}#O;ytw)C?WfPPo+_E# zm{u1FMd@iyFNIckW$9g?enL80&dF|C5(w6@$;xvo^l-?|_Ia=cc0R^A?`^jD#@|GE zwUWNCys80dnafu)^+NztKcE<8+Vx6SQ*=_%2 zXP-Q^!ELxdv!QJs=h6VwI*`NBb?|v{GuF?~mR!L?K8qV+?5i4MReTOEgx_EY~*M$ z?klfjRDwB#+t|hvCs@y-mpP11S@2yefUV!xsO zHIswuXn?z+_B$jOku(?47yC)v%UHXrG)^U(RD#hOU>z05b8KLrf|k{&wL~k=UUZ~)UXQAHZg~#Mv0N+)y1y$$kGzn z%d1EC{9d<83DB>>07J)Lamg?LW@lpqd}#uDxWB&q_HkmsfC?BiidUgIf)qP{6`A!9 zgcn9eowHD0eT+*pinSxIINjj9`XFGMe~Xjazn>zMVfGbOnLgtB+zI z^{puzKli&E_2vVsolgvPas<{ zN@q&woaxs{*@K;Oy%Pqd+~Hn@N%oG<;Lp-3Gz;EkaCSP=vL)}}Mnsr}!pa!jZ-6GfNq4aUd^VsEqA zh_vcbwNqr4N|2&f=R#TS>g7GHC^$MkRoZ@5wVgFuPt31`x{uM20>u%7lik6<^>0<|s8j9%)uQ{$5G9ME^TfnJ^g$7$0% z8+bXjVxa=E1ZyNxji;Z)tND;*89!}llu=sc?t=(Zcy>u^bOh`pwh`@ILlnBL@QG5p zUVMirVS6uu^kzi5!P$fZp{`u@3HPMGJ7RBQ-PB|5f^H?1M^gu?4~d<#wz=~(R1>_} zR>QaR>Szg83o(f9gSKorvury74@0Z7qnI0rn~-<)!5$^6b8+ugP6;P*`PqhC}?ZU_CD^raFq=ORC;A zUc%`?MsUbtV*}Ke;Iu;UpH?M|b$HJSoF=Z2e>;M|r^Q;pgzSN2rI0$ zaSvRfp)senzHpRUkKkAH41s615wY4D7U}N`m5(v{kEKJgaU}JMnH3I(K`K!`K@MBe z8d!whj5>}5&|^k4U;TLvf?T1k>~)hBxPB08U?-u}WZ}P)!he* zT+E)Z_Bkmb**FaoRM3PIS##>N93~rOMj`cJEEPUemJ8(Q(|%QV`RD$u4XkScf)u~Z z8^v$7K{P7OY%RjP1H@REz4>i=ar@^A!|tZ zyvVWa#My}=^ySh)&$0bel$>Tfed~J%!ohm0OFH1CZ$UAqcPsn6I9+k8Y}?Bd^#n;d zd6=)vJl31;p3(ZVORVj&@T(jYk@25Kr8+fa(D z45Q9UYUpky4V?*}B86sJ9FD#hhpx{KddL=v#!Qd^T`7Rs5p}I2J*8?xMf;6KMo>rP zB4EhCJ?cu#9+#)jcL}|s6b+iS2H&bZDA424`80Z4E#4{98|EdQNpjK>W+iz^Yp3rg zBT>`h1g49FC6TxXg{s^_9zPOe(NoNvI9{vK32e634XVG^*d&6bxE6KT`f>;}auk4U z?-BK3*UV|h%Mwieyo!CE$Ny0`RD7Dx*>(-$QQym{vucgf&Jpj&vF71a{z`Q9m45#G z58;_mIadL88Singc29+kQ~vZ@r%&}6N%V^#4_z>R-8I`~k)LtjEXj`7p_f_FoU)j$ zEzQ}`k3UvS07D0*WOpacC3{Xo_R{gGfr-Yb@pKN8-3JTMNP7amVs^YXZ_R6vl}z=D z9lPmNhsI1L^vLjZ`Fe(f()V6u09_&X@N%l3ggsnHS7iQ%4or|ZLp9Z0FLS<)-+b{y zEdZYJ^rI_z_(PW@g--?!kC|&a&sqB(=^x%Czjv!Y#YocFs72`XwM*qNFmNEA?b^ew z;@BXmx&>96TjGHLP;Z1U%U|e#Z%^SdU9Rcd&>=BZ(-?GsUpzT{E`H2p3;ANST8$n> z<`F|O9r;W+!9vda#{2QQM_wv@zl8{Nyoy+k8A6^c#sE$TJhY(Hhr83ANG#=6rT+Qj z#>*=kMp}q{3k!4@CO|v>PsHkMXauxj#^1Z&PgI+DANf8egn=rhJ&=NhF zH$5?o4wkv}BkR^raX;Y*s-ccE1m;`SxiFrRMOqS^!#>EB0^Eqx+Ge1Vs45y0a{X2n z4x_FumOwvau*u8?N)KX|a+FJS?1A;jx6W9yM(JD4$m}INEjx)(KKyXHP4)}u2t!If zUb^(u^yt3wufv%H&mKA_-Qo+4^v7myM`#ZFs@gqQwF1Npe^=iP9HvU&|#79f3GJ|pO8eQSY{Ff#5KV~aXl+PI8li-+}qb+up%>s%ZO69XST zI&-0EmG@e9`o#5nM67q1V=B?6`Jm|P!jvsx^_Tb71COg40;W^nc?ehnY?<&hi2Ww* zig)F;!oI5X_IF#F394BQ&CE*r2afn8LAFZW;Y`t&G?#=pP-BlnATc2++ZL)l`S{YyTC0bcw?$&4XD8oDxE?Qe* z&dP0lE+%}iV%iIau3+!cbhbzz-zjZ^M$)aStgh((LpH_2?`j#+V#NFbd3GqQ@_RlXmPTzKOiW8UQ zL?-Rq>0mE@l4%=$q_X8jcjUo06Y-w9xrr~NV3|6*hdYwzGb2(bqJasTg0so?g`I9- z(fw2RMMWkb0Xo`55bw!7H#K*Rpc@06}_mmA_7KlIB*>sumTz# zN`now&<1DRBvPv(|XHvQy(*;O3O# z?E3D%54huQbFVoMi0o;53ma}ZGFvEb1pjgzp8 zr1P%cD0d#vO7*L9b&0VyqNU)p@9Ymb$SXIaxi%t$v9z>tmwK8qn-yJd(j&mqX@_Z| zZOiGNEF5HHR(g`UKBTzy7+gNtk4PZz@gC^^&=sxpy;@3mJEo$k3F2E*Og~en6dsH;Mho99^bXkSss&bVQJ_N9>GSPTIo2xTnbEt@pYJAkKJP1Qgt?Zy|WkmuVH6(4q>;KzkD(#TjF1=!)68P-p0KNhu{}n&}_X=!7qMX9ouZ1FM%ZmPJ6H#Hy`V~=O zdRh_<7gY6KIZBgY!MuxLNMHU$lR2mobH>c$H-Okp4}QI4zID5fu2{kf2NHF5r^Eq= zx0cmB_zzH-}7b= zJnQ`i3T`_?EV%b22Tw6x>?2lA?zn1Rp5o8-7Ao(Xn1&UM-RO}8Z;fV9Bf5=3&a7dp z4n&{O>zfoTk`^8*2n`a*Q@0=9^tePq9LVp-o}qD}c;*lUN16~@+mOgq`x99_i3S~* znDbw1X4EmU?Dr!V19y5Pz~*3`a|bC)hArS*v|5VxrZLGm%SUs$uvF2@-im5|R$V#z z$w!Z8m}KL&W5@m-+HzJwZBDD~y9Md~H*jW&r@81eRgn;+Q5n#Vn44o|g=i|_lM{VH zgv21my0bdAjI62s5z_3;pLn~yG78dH$IZ!;=*&ej*5VB#c!z=>O|gS3eeAhA04o#l zukcP?KY8#R>Y5q+!*^Qb=`GiYy^E*_Tc{+8x$;; ztQ-S}bP*U<{b$MI*U&ndo0_gHu(+}Bn09)?`$Bg2aK*^$?e;mgxVx(HYS7s{eMx5Z*<7t#v?;_or|MJ(?w zTP(nMllUCrQLo=<2cCF7LGhWEJlT%Y$u~*9kc1X7ry~jL<9pnLBj{4rus@eapgYR2 z7%1;6#WHBoxY&ONAL@Qv@0d&3#v-6c9?hG>T{bVl*iTqN6XQ~Nr(uUdw@-g(^L-DY zgCI|$j+*s?x>i?_ylb*U+9`#Z02w{!px04e-3&QOaInd#%o9d`HdZ_1l4muytMF&s zp21D@?W^@2w_DPXXkceu0k{9NvsnL5Ohixd!T|{Y5YuI0{QgVw@ub6*v(1Q|-K13l z{SU+={VhIgSz7T#VO`U?5ap=Sl5n-+!x0rBAc`xX4ZhW^i>H)QBK<#S<$zC=VGmDW&P>{XJh z8dv9*6_t6mxtUdk(+{Z_?+lR3-z-(#g?-(VlxFx~hn6wKvQ4Zf2-Dn_yiheJJnDJl zNhhD;b)dL(z<70U>J>M1eCg$pOeJ<>>N0M5-RPOFKly3g)h6GV`5-bxQ1HY3h)1(k zicb~c>F7c0u)?JmdmA57tmbuNf|y5#Tk2Kkmc+AjNe1NA$2O-Ma=+0B{e!blo}67i zV+?|$a}m(`5OX*yZ)P29ba^K2D#N;+G}c_&t2rq+bj(_?T| zs5&%xQoNw>h39kF`*1jZTagd4r*q| zZmJ$xsuRTvP3(-TpfiYTUQ~kYAD5+M3$kA{SYp z`%H>@abuqo#8lA+I*4b7UZ|x~FrDK-+lBW&8-@0BuYwdvXC-JT}fX=iV>P-M3`Z zI}hl)*rfCMcx*+s-H*9XMdhY;yCbZ_>cr-924pb*pkjK{X8<rQDRpT?o}3URTX~Pt=W=15i@AdT@h{t zsAgAWk@lB|PmiKDo67@nK@_{N6}vbVo1y3%tvfy)uCsAFe&edCj)@#IY@y26m+Ybn z%5$R1Qxu5zWqb3>HlQqTtn-r{-a)(_;A@Q?;2emjF{mO7pcE>$Q6@t25Y-IS)&%p? zbiU|>v)&L=h zr~c$Z&Kz(K@r`YEmib!NqpkgusRg4<3GLWyGV;tU2jO<%SDdraS~i61N;;W7!e3vl z-PMzsujRtWu!0O2jzcspPaF+-l}Nk2X^@!>9NEf2+f2qmZX_?kZi;J@z>s8D#>ByF z9eXMTCcb_yMXnPwhe!<;Lr9H^VK<0HAnX+@?MQIIg0?tL8 zi@-&Wh2U-xVanmoR2RuK7r_KxMLvR{f$|3GINloScqDK-$6i>dhsNeDzgAH(C$b-$@G+wH}f4-#T+ z6K1UtW}P;`o!_eM&jn4)$zwNg#J2&dgOsz}+EphPJ5A3^M`oBfVVJ0AnCJ=?&Dz(>+E*iqXP%_3le+TW{9(CrUPsUmK}psuuE+B`K8rbhme{@`8Ba{}wW4%fn={XwW;-}* z0dw{yEA}Nzc4%hG0L0YHH~s#iXv_X@vb4qJeHGDn$q|%y1E_26KQFFTF6xvmdefCK zNLhCaytnF>N%+;yQe3{5N%$1KO`H&y%&XeUw#llp!3ya?mJIJPb(!6Ol+)@|^XfxT zX4EzWH)6wp6E<@Lo#G3d+>v(Zyb(0>|)HVL4B0~5kGk7JGPGSJ~q`gY*@R& z&u)&gw#~$1VDdU_ppzr=lJR&|Oc6azA?r;ci%pO)?69`oGTQ*KkTeKRN1n9k%<)0W z?iS+S=r#9__Xxf8$G!CRz4U{V(!P46-Oem@;__8oq{XbOV0MtXBZ!%qjRnKe>I4Iy z*Lo}0M9S8{GSexWeDt`1&3NJ3Snd4h%;n<}H-|7`n#GPRepw9T`${Z;0^iI-B& zMrZ2zU?gTpN`4Yb4;LdJ9^n>_SaXL|LYSpLo~5s!r5{|C)}cV->X0qRC}&U%QR?LDJ#D&eZf#m;t`&3h z@mAPJ%k1*3x2oxD2_j!iFb+DUyQN-~wgUA&WyYR5ZYCG&Ztx+;W3H1SxcGW{`kfmN z0H6iti*E$8;knB;CoeZvM)U4G9X=e;FqXCZTAj@>Ox2DaDpfp}CTP-^`4QG8vI06z zH*+8?vJE^KYJK6pKV==N{al}ONfOh1TKf=!UscSn+#FvtBD2EDwSN*sl27qPRNLdr z)jq9W?e@k6R-yua-O{sWKyA9JLhP5ENV#u}Pnf#xnpGkxbT_EUvB(N#VVg^UDIsF4wTnzi1Kdv<6XUsT)C5$nrWsSJowp7ZLsS_?=#wUYNEsq!7?rr%OJF*VgPk`B%u|rh~z);S9-{?XHV9pi! z1^l03C(%Yp?l|y8vI^^e4Lg6+4?&0KUcHf?hVE|sk-4^^?TH5(X~E>XGfmK zu-9YR#gy}7>mUG9#Fpyoxqc*0E*M#8Zfxr$HMHp7)_inr`+%+YiQUIM`qWVX`$Xa$ z?M)|h`2CwZz0S;L1iHqfBKO?bBtdrM3LN@DRiwSNMcon0{KBE=`;cWi6@?n zM7tY-v{q?-5*rcj)EwIY2?uJVlnC70q^3RJj;(FF%LOC9EL=n77h+t`kFzp}1o`z9 zx#&r*Y|at0m7$Z0t8>%b(m&($!rn!#XvC~&Oq%x1wnXoO4V^5tww#})NWSH6~dgT$V%=K^L3CR5g)r56^g7(Fw_KB9XC!i+4F#9pB19_FBlNiu-7s5?zA z;IxX{F$trb6wl%8?WsC%a0G$a1C4k||9k5yv|wohu`3#}lJWPCl`O%d1Y*ZDU4{Pd z-PjH%aTlJ3B6SQf+9nv7B6N+haRyGS;G>MNmmtM!@Q%RpmsMQ?X3}^Mqs2Qk^IP>p zhQY;k`%9psNL7wO^I<-@cfS=WBxH(EO#5}}6g0mHgXu6<{OMQQ$zf=5{{9l=Uv0sG zZSQ`y75LTm*QrzRUu|)t#Dg^RJ15OSq8`F#KybuLxIn~FX<+@|2TOw+VC2^RI>iSf zZbxmvh94bTCk~!9gMx#Il1~D}aex8hpn(CQLxIqyzfO6;L~ST_zpW_}=}mXRwJd{y zmqbJ@g`=z>)hIVmq79^gqwFBn_+p?$7ibDcIYFvXX`pmM54AwUzG@vWPFJA?Hjf7H zB;&6g6^SW7I?(*?Yk_W*45s|yK(p-E0{y5lOnJCP`{{EPxA>LbNOO3`+Tc*w5ALvt zWIE;c9frX&7?qq+_NBeop{NYX%^OU;dvHs5oqM0Zmg1AuUE|Cw8uy2WrlcC;;fgn> zE>AP{QUH%p87Mf|qU_()I zVz3b6Kpo(MJ!lG{riYV)uHj|T+;c8sk)iuDDN3K$Q`GJZ570FmWWDWD3+WLpu(0s5 zW-|2xV-%L`BB8xfe)OQ;$Mj-uPK$QO0}%;tW})e@iiEhpUlG}8(g!A*?>h8l ztcCDAhzq3H(nLcwnr#nn#}8`?Q}rNfsF{H$(+5Acig)o##oEt2A5?7|O#X;!mxD;K z1_G_vKL5I+98NaDpF`;MNS9vayy^^7cLzeQ0z-t?H?MNvhddClNI(zxfcC$7z~2i9 z(aX9{8C)3tU%Pr8Yf=V?E}%6Hio{`DKJX?k0#4bPdq2R1VLGmzR_TLsFn`Ry*dTF- zxTBCKZI6r-Oh-Q$ebB^G-2qS)9-0kVAW`X2PC&oEk|r7nrb93Mc=?U3VOMHZjt1V0 zIin(rWrUXZyw!)1<-A`L(_=utU?FpiCBDnG9R+(c8_-0cf3+jkz?<1!mPoegbY0;a z@41U$CUupdF2_J4b2;85IGMB3o-rMM#@)r{22lI?UN7Ws21%f>lfMq2tiJZpQWe?W zmU?~Uqa6OAkX;&w9b$Ke)%Xct<#|y52g0T=rgV61o0QKO&3jLM%7L!-!^$c6%9_ra z*0~22ezBNqGs`Ly0nZM3Kkz3+A8X|&r>C`>xWXsvTR;;?y_Z1it<~(gB8J~VDbM}Q zVxv+v#es+qCiY;}gu19`LJ9eKL9<4!4VwE$*Zht~SC0jOzK#S>ze>h}K%bZ6@+qB> z$1QH@O=+)wZXL5zS=O#`R07;Z!)zJ&Hhv{^f_lD3`JfMgQJ0KyE_0Cn=M0frf~0rMn|fpxFAZcb>WLTsy% z{?a=7x7NWnFs$t;5OI4fP^_;}VB!u~;8;6Rpo5gw^DgYpy8MR`Peyydn_d|BKQ7Gcye@Fq+S6()ymXI%46kEu55Z+*k7^&^ z^M0$OXP|okYRKPMnRE0A$zxr@qe(*#dp~Q(LpK%Mtv|%W0lS5X@w5c~YMa5;P;ZSH z_`l}&8~4XPHq2fa%VOAAtQzhC*r7~pLSQ7!-7vkwAk@M0AjUAp;3g=w)c9_l+I{?5 z{SBKi1y}g4dbm7OhGzI^FyWx$DB@6(Bn417qBwZOL2+`1n=38a98Fd90#ui&>d~s- zt~>0e1gwAfS=8!(xCN&;Jhc(+nm*%D;FD^x4iLzO&9x1>RVO)EMPoVmB)#ee*{Mse zx{9BWegxa{AfuCVyB-|D>Quocc`x*oH2TTuQ2)0K%{ij3ho!=R++KFMo-Vw3LF zG_mRKLN@vId7Y4Q4Y^i_!!nfx*Cohs)}5{MN`*3|o#*B(H+%2J1D&FlPSBnd=|HLJ zP+v?+&v_ZcM@A1Z*+|M>mm4_v7K*IK04 z0Iy43{t^cP@dup;Li|_Z%WJ{c^&fu(?|`ewf662Nts3Mt*6ZSmKUfDq()S;%ze_D% z1H7(u_ydpubg};g_*3`r8s&9K!5*UBEz%Js~fPYdYuTfsV>;6IEp#4{rf1OjW?xM8Azb>0Rh1V{xSi- Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/wolfxl/repeat-1-output.xlsx b/results-2026-09-08/mutation/wolfxl/repeat-1-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b045fe9db901899ebd08d224f8eaf4371843f24c GIT binary patch literal 15726 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 literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/wolfxl/repeat-2-input.xlsx b/results-2026-09-08/mutation/wolfxl/repeat-2-input.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7 GIT binary patch literal 15042 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/wolfxl/repeat-2-output.xlsx b/results-2026-09-08/mutation/wolfxl/repeat-2-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b045fe9db901899ebd08d224f8eaf4371843f24c GIT binary patch literal 15726 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 literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/wolfxl/repeat-3-input.xlsx b/results-2026-09-08/mutation/wolfxl/repeat-3-input.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7 GIT binary patch literal 15042 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/wolfxl/repeat-3-output.xlsx b/results-2026-09-08/mutation/wolfxl/repeat-3-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8fa6f2ca621f3f1ad60d06c04f302941078bcbda GIT binary patch literal 15726 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 literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/zavora-xlsx/repeat-1-input.xlsx b/results-2026-09-08/mutation/zavora-xlsx/repeat-1-input.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7 GIT binary patch literal 15042 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/zavora-xlsx/repeat-1-output.xlsx b/results-2026-09-08/mutation/zavora-xlsx/repeat-1-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..14b5814969c508fb9564b36cdff0cc2613da481e GIT binary patch literal 14211 zcmaKT1z26X(l&0TxVuAf*W&K(?(SaP-Q7xYC{A14-QC@_cyar8d(L-z%02f7va?sn zyiX>XOeQn4x1cmD-D?%r}f7xFcXcFFus_Q-x_+PTkj?>r?I{Ukp%cqlo(&lOtCy z)0RjwP0|DwcDl&XeuCo!FejV(@rX#zVcie#BzYpyZh z30B1<-Zz8wcv?`KWxk74q+T!8lpDGr)da%5ez;*~CBf_u7`vT?KWnVsV%Ztthi=M84w*a5Ka10oe$@1bB^FW$!7Xo71tm^vLPkCy5m2P{GAK*!FPXeRT{FW4La$wwQMu1}i=9J-CKi#8#@vSrp1{$}>UoW=^?ML_RsNn6 zbrcZv?j0H@C!vE`+@Q~@IJeNYSf?ZB=yHE7*hRMZ;sIcxBtd|H-T-P{2V*NoI@+I~ zsR7iLrG*KoX#NHR) z447TG-eyq6d6y_QG?15Qdgvs?Wgz-NdCryd$(YZvT}jiFzND4R1&wVmGvzKkRno@4OPg^CWDf6SE2a*#-F%7v!x6rmqU$CW3{Y$^B zU3S63D-wfHQt;q~HVN^94jskK_lviRP2-l)jLefq7oV^b-P0?KQ%(5n`B#-P zB0O|#(JWL{EFrCF-L2&9P@!JT1%YA;Mdxrb_rr)pY@ZLrr@~xtN_m^6dcv7Fo2Jg- z3{S<=cMGD=S&?uYG~DkAA4S2bc{zl#(HEpHI?^AJ>a&k-Vs28%?$(!FY@$W@{5e}V zdPidNfDK;)kRSNJX6v8x6cw*+3E1qxr#DnJ1a2%-Dj0cRQFrIb`pKrWC1>+lQ)A-u z6n>72l z3F_(=ze2)gSf|@-g}7~*vN`!cN!GnXsyZDd)x)xk(o17I@_5_ku< zypq{6lEDLh@H?2eOY(%daLY9T>XhjK57qF&4Qh_o^+r_l&+S)Is^47Y#2r};tAG4uCn1}z+B9`JvC_1H458^qtn8#_7D{i+y#ifdN7c0yh~YVheLm6n!mZ*sS(YExZp2dm;Y&7{Qz zD_X^`G)vQZcJxn4y7*SOnDCYPGN&W3Jn$g6;>{l(+MmX3Lo6%G+>zBQ zGo;l|cUO5|)SkJo$%-n9*@S1N9Zp(?5^gTL)=qRYt{=?ljM)z8qC*3`+Ilzn~WOMJx{Xo<M>+j~2ohO6uXPwo{Q+0nH3EF(9U zF_jq&b1{6X@4XU|v|MXmM(!o?A~a-HTX9QkxFE?+yY%O9e3F)ElayI*@a~MiHhO=m zwZ7C<&$i`iSv|T|yU}+aIKe+QBChLkoOxPp-mO_a9#e%M9hsAMZhYk8NW9uf4%s}u zc(H6axPFRzF`jk(@Z@=z-ql7SLZgf=V|`1$2xURcGtpbb`b@qEHcfUblo7iam~DnE zpRtc@ZD4`yvuyIY@PM&EeF7E!#`==eeC9$u8{V6PF1f+=P&G8X_5JWk5#3&)Q}0%Y zX+HkPI4`%}%`T>7{EyZ5XOYX!y6wYx(|0rS4o}13 zqLSk-I@5EDqL4B((zKt=)t=uzl{h>mM6X~oGfFYH-d6lweIW|F0!(DrM~K~4Q()M< zLGd0ADMcVJB@TH{&o!+c@Vadj9Y+{kj-XwZgy3DjF#*Rtbd-=Vn1e7Ja^dsyJ9n`d zf6|iubfs-EO2#oUtTa_=v@}s~#5At9e0H(G@Q1C3U6i^oAx~*a7ZTKr>{(`3x;tuC zx(s0}z)D%2Jce&>iL$Dmw-+J}u#|MiDH(W+Om@E~RtK@vAx&zpkryYWzo0Au=>t+fDl9<%~h(QD0 zO+f`ivMvZkZ!(kA5l)|iu8;O5776I>FjQbM6^szO2O*}Mm@F4z6-l~XX$@>eV1pHO z#Bh`9AkigpG9r|`IuQcbAe}#X*hPe0G6k=7O4%YK2Fk7jMPwPc#T$3a>v8$ml)K zXqI<0*&7fLFhGEB(LfNPVEw>en#pXzWLyfMzgIPo`AHkx>S@;xHQGfWiZ}Gw8fB(s ze+Bn@mL>0x&C!z!7FvI9Aj^?9x|MeBR>#}eEhivFFmMjcK=t7VBDF7p?xTc8#D7C7 zB#<$D*3oH~61352Ri^;5{+SVkp&u4Fm<3syuS_+)z3ZbT(t=YkJZo^16|8D-2V@o@ zf`1fYtnVm-o|?b}7~XXf86i8Sv_a`OtW0oICM^6gmyQGw7!z^qr*W|4BI}Z{7zyNc zjeOWJ5|skXVOZBR%nB_*UkSr%GE8_H|C({IA*x4>B0rR{b}t9-@{M@~oJUyKJ50Q^ z7DovnY6p>ZNOGxnNF4?dWWW|t6??t~gq@};<(SlOUDdJhGT5#Y`CyZS`;wnLa-frS zn4#sZLc8@W>MI`9dQ9k9mW?gy3((?`e7y*XeN`NCpwSEfU93af6S9yuW^2kZtfK4| zu=r2Fr-S)mYemcwKpgU*(TteG_-sPYFfp*D%apYkFt9fmSvxm%6+rZune-jsy^*e> z%!97aK}Ce)GOq~xR!9Y5N~|?166*)t0GOFCh>L~3%Vz!sfLV#fCd%~tHqouIfy#F3 zmr3W}-?3gwpuhUWn4^2LzVzwH5=Tsa9Z&QfjOQkWFwyLXN{r?xJ9q4j3~3Ds0$^KW z&j?gaGk;+$=}#KfM4jNNfDz5;GNb}V#3tY#im($r4E}hYZtj1jD_x~P{3C*78k1Mr6YL9|L z2*i#(U9Gg!z>d9h#|{itU(Vrc9B@P)^lT7I$6(aB3ph&%RH%-OkeX!Iv!1eb z;w8JPY}HJ$%!ZfJzO&@E`ds)_OH1j#G!#+P6z`aj5{!j2IMipy7RQtIt*q(7Gb|-H z-J`?GsW-dy{& zt<;%i8GDV2cTb_kMau4n@3{>cu&Tx7l}C;Ym8aL}F3Fc_Px)?iuJ*DUciE*dJkGqW zb$srnZ3g$cWZfH3(1N3CI4&~1COyQ}C~f_y#Cu&c-+%pB`ciG3F7vW)D>tBB?LD@*dDXl; z^AvIa^uwW;_NL8y>;8=QPjiZ29Nc#XU`D9|3|iv$kPZI5HV7%zLe61`3;ky&eaJ&Mai=$QLz^_*5!|Ai_habC>4^b* zih>N4N< zoSQJ>{S+ThZ12J`flU{Jo~3UvT&Ao3u$)D)6Jfje`GmDM?9#+IedSqbOxU#xOCutU z*m4XUedT)KdwMcji1$PTWBJY`)0nV2_L4KN%bd;J_s-IqLf7Nmrpz(n2egUs78_WD zW_VAUY#A-M)Fo%d_Y)q2_~}h5KZfm71lOm6kw3aN0|Z~K3|Ey}OVn$+o+ zbvOF1?!tr5+B+GmIp=hK+*&gDT-CEQyp3WP?i3!}&XBzm&uM8lD_MiGT70xTavlOZBo$S-ox>ak}eRrOaAYZ!DVclNv zr?SNC@>mT&SHS76yV;b-p+(hRR#;7b_%_g^y`9+5MjKUC;Dh+KMbKPQu#dvpav!V! z_ia}0*U}uO#A{}!=t-V@X~a+ltXYh=mb6%sSxaIzcFW!s8E;O#BLZ``T%L%0(OH0i z77ubT_^R#LJJf`=ej2mDeY2tt6~c5L=(9rE#YH3i{_n_ z$*=e{_k)X6&wU5Un`d(IlmGtI*iLb6r>%$LQB6x9&aI4&k>#GZYBrt0^7%nI^u6A+ zaO8(}3V|Lx`f#~0$VeikL*P89BzHj54j%oXx79R$)cqF`=eEo^_{a~T^7t6S#q*FN zh?M7k@_`awdMG)JKbw{zMOtE_Ao3>kW{WGCuz>P-448ocz2JNSy+8oHCV>FGsDC!W z`^vu<=53fUXR=`JM+Uc>`C_~UV1)|;dc`9EdNG3mdc6TO4GQWp-_BF0%Y=11%$gUE z5GC_jgo-KCo1=CZfG21mQp?jHpmr#LCm0}7E7F^zbvS@0Sae~2lZa-`$d4;fp#ioS zKysAy)r^cll^N`*7uv|zj+8`|Iqa#I+Q`?9972_WnY9}~OLUD}=#DT$rZeF00%NlJ z|9lwro+U=dEqF$nT{0L5cA=Tf2M5y(SG|3!nW~SCRZHK+%50?{Y;88*3A;32#bW3- zSle&aDE##R&F>Da1Bn)di8e9xb zV_kao8`LyZGD|t18jGAKlC9?TD5k?<)_1hvZ~3)+6`hUdm2u4n(R*KL@u)smU{>0% zIMqMQ;}>zwelA#E%Jo7LrKXg>L~(6A7xrI-E9lE19xQlj%(-1)lg-VgZZmb?8a&4I zIqe_ZQ_EX@2KrO?9dd#}qXKl_J<|WweM~=fU(~#&V+K2h??zjvLv>0|>Mh@_Ng+-k z=a($;3~nuCVk>FjYJupbrz=!FfSwnY6O+3GOywGFgZNk6+h%QZI&3NQmNCLPB!Y9ectC$sKXzR z@L}irrn;nZBd-&9JA3RoSa&^qLaWVm^x&v?@oX|1QzuQD&a0k7q>`-3mARx+tN572 zeSoO>AWT8}`I+#FxK!%EFbL)4OJf@^Ra)>x|FIp}Qs>k6UEqWk&Fv{L^*+0&F5fQQ9U%VF@ z9knRvWH1dMN+#06=VUQ0DWsUEvtl9I7IJPp+?T?T?S{!jZ9N}F=WqH%Ga5tsKr@}) z2*p~N-mKFG+)k9)&Z|wbF{nm~fv6?CX zcs|r!sQZUo|6_dju1ytv6-Ol%RAon4PR^!oYU@M+5q=SGX@O}O*gQU;a*D36N zv@{JI#kfC}G+REQ47Xn*f&u9x&oMR)BEako#or>8q92K>+Uvhhn@Lyr|@ zRg4U^N!1w+9jv~QFGFB8Fc|_Fgctz{M5;h47C}&KYe-#I<*uD#Lj4K0pOcHe>Dc%} zP!_kKDZ0xwY?k)?0@JI;v(eF+uML{Dx0wUnm71l~mmV#fXZi&%k_lbR9`h5DpicmM zYvPm*{=-$^0Nnm%5W->2Wi5(>6*VD8=~ZWd4%PgkvC7^ttz{}+`;6}9`<7F5h~S~P zXU-2hq+{kj1h?F!>AbmgeNu+@~9Bx=NsVr+n*!xhlga@g0ilS9( zf#dLH?ldyM=Ef%beab@E+=D*uq5SipL?Q)Dt6}v#?v+3sR&p*0)q~lwA6vOMW{egc z_<-zPRVX8^D>&~fzjD?gqV&SLW$pMHjv=A_HWW~HlyUr%>bZ@=H2*;+_i&dA9%On+0A3|7|Ewv}Mm z_&4+X6NmeIg^#OpoA2k|Lgop}KyK`7+sAY8`ns*cY(OJ@9XgnOcur&{I$-Jd1UVTQVZ^kXfjh+rJFyzUONk)TkCW0})AD zTk4=8BP(WEA++o^#;>9hOcD`#TQT3(F0zF{37qUOW-f)IKGuS+l7bOC;Dh-AC%tz< zc)0#FWF>1yFka_bXC1bmOle}J(nDe}BIGCo@k>1I_=Fx)QuW*Cmxips(Gnuii4TdI z3)TTwg{Jxw9(m*DB&U(P2t4#uWRTV0fZX6hw#%P7SL=jMl}a8B6BOTD>*s%o0GGDu z?j|^!``WLgKgFv*(5ijgH$A|gg(r`^dPAQ`cFiVS3_YQBr|@IGGsT`-9SKfHCcD$i z54Cks{7k`z3C4)^p$mmo%#hG;*N!Vf_RnJ=0%O*u2(V_8fbuig1&9ean&~?j8!0+D znA@2CT0-II5tz=O(EuLdc@OC;0wQst#|C#xe1fl**k-IO8OeuJOGKOcdORi&BDmyh zVTi;{d|0eUIA98>7NSwXHTA|G2$|F~wQmBkbo%X>sd_TI-;>Uc7f$2nZ+{lHb;tdX z&*2`pZ=KG-8vhVlyNkwfCu4KzN#5cNmJ0()`c@MGv|-P84+3Du+R&zw z7Tv;9G~uGvq1(Ocw&$SdtMd)xUPS3LI1rEm_FwTj0Ao&O#@5Dveg5(tAFIp8AhV&g z-6*O#h76D}5jGJ;ur7dUsHq)8P)3hNG8t}S##ouAEK{{Lzmura%CZ(5>d87>80xqxtPvy%5W=@I85eA2KT6yD-&lJ zP@VA9U-F&N501f7lYo3(6x2aiJygF$FUNZ3BF5NOyLL}Vs{GT;{{3B1J{7dTJ$DiE zhMmm*kCiA%F30C9{};xJxg%$f(M(;q_Ez|0PD!=8H3v?nk66WSTDvRd?ksiTbGK~C zXV_UXeM`mb*l(Jf0&Qo~Ph493UD4fa)n7(k>XypZTfkcz0#9`p%^HJNxOm5xm>Gz#=;cea0zf?^7C zM%J+?!LTz_P$GpE-}`c5`;9 z%st{KAq&Uyoy)5SS>DNXuBT6TxPD;v|X8)8Wf!o>)ej z3U8caP$Dv%cU@qvAPUMgM81I7)e=29vuEqHx0p^Ni;I3zi`I`Y_}Z5w53Ms2YXxiH zJ}_vvmLrr!TW&i=&uANKWlS{qS-Yf-L0U&S5;Mr+F$ZI8ed)}?z%p@Nx!$$v>||ZM zMpUoTr??6K@Z>?wRdwg0amGbn&$@+f^sa|0V;j-;8{TO9bW%dVFotYr@h0J|Sl9xK~MrNC#7kuqp&Ro;41em{L42#9y zwdm2m8EOa-6JaMXj>O3$lrfa9`=)csBE2ZGWi>eq9Zx%|O*qOGLNSw^YeZK>Ecuz( z2~5M?c}##uW@#3R^PO9y;yU>kkU(`PRl!zDX?JVJZ07l9nyf{M04gE{!Wp<^dHy82 zkqVjkpl9c?kw-foh1u#YZu zJFR@TFd9_*4RITi(hL+#WC71wQ>!>s5LJTs@CKY2u7P^|O@*>@A(Fv@mt!Fnht_nt zzo`6nr`Yin0yIpLjIe(!xANj0mWhnEPunO)lCw!gg;c~EAqR<7tg$WAmo90 zetYr&lZ+ZmjO&-atQbv?glj#*er{>HO$%XN4^*p6=^({cizAbWqt(UAMHD!EiU7X&Rr(@q!!5?S4@7!HR$Yf$U)MlwrszAXAEvRwi^b1c0^+<}uO_xHSz zroxbr(?a4uS&a{YlSl`!H~=UJ|72C)&h96t($O6-AcQDDr(QjqUXDiyh=)i*dvI64 zxwfw0Ug521M@N@RxFLS}-D&}+D*ZjeiB@&EYLI5R&g_!c^|}wlM=<7J7e&DabmZoX zSvQjn{iWa}=3vxFG(#uDE)CG28m%&VO$t*33WMEu?b9>;B$>y6#5{RnA>opMXy$pm z0;IwmB~~$|ttDEnu)ds>(kY+$5Z>Afc)dD}dAoSjzW~Nh1XwaWKyB#k=wxfHX8nH| z2Fu;mU}wE@189$KfLDpYnb$Nro5T%1-mJ;3rhgMG};yxGA3tufy*l@U~ zFeE544SY1=%9OCIgJQ0`$bGDEW~o(>`^Gp|I+SWhVcTzoMC@yhF%!f6D}4ox#M@l* zo9S=&Qwj3R2}>PyKKUDu)-{^MK2o^wp7GAn{V8fcwkv&qT7v6<@-yQ8=a_$OuwN^r z9X<5Z8Wg^H3Xk??#?3HM)$m09FVNF+h!e{>afBK$Z)&t!L6ve=Y1@YZvD zbe36`NuphX&5UdIhXYRysC7m@mHkGQN2Tea*mQZ@0-n zgzq&NC>ESO^@*8~9Day|&TrH_Dfgm6>+j>Z3cd!84$SyQHTTzWr%=J9mZq5pnA?`f zwnHnen+?3MWV}iSssrDHWd$U1aKZk^%ryju#sLpEICkZ4O*uDPD{r;=QJAj+hgpE%TOjUMA5P2 z8SMTY5))5IUB1ANU7@h`R)}+yFKe`|14t|U>i4xmOUXEb&-$B{Tum^7)omVY#+d7? zNf^4JIm}A9XK!$+JeA+OY>a?W7B{> zkw%_dlfLdks?r?NcF{lcc3Z=p7cFA`P)w+!ujx&I&9Shru#4J_%+)trqIWc{kIja< zG(XU*s&}MP<$P2nogQwzX_P=!#jR4sJ*%I=in=sCP^hZs@fq;f#cD}eo0c$A(LP(M zcQm7)0iazT*agt4R$U!c(Ew;Sj3P9wEc<=zEF=uGKDIgVod+fRMY!S<6g@g zS|$f7)p>ehdYa=)fhBfndRx*1hl9nG)S3k@?-yn%88+FDS*gh`cV_?A$5^MGwFd8` z>u`@oBKeBTIG~1^E(K$sx4^QuHUkHz0*{b?ZX(jcq)#FMIpYK<>%Xs4|CF;|(S+kv zY1_@8at0GYc~uLs=)h-A(z+n1Tw8w4Ln3pwIX^M~J=jNg2^z&8D-3NXQL@Z!7q^WG z9ukL64fJph1!Qp$iFVr1quiO3KnUD2-S_^TBBc~be5x;NB}M|m1~0OGr+DSm0kUfD zv4_nS_Xu;5$$%%kdet>IMwwB)rh#`mP^+B~h}73Gnk4VKaH<-irabdVE;WSTj zp4K#{V1!#OTL@8eq{nIBUK(8vdl1)3D}2p#CU5*kNl|p|3sf85l{Ye(*^hcSs%r+o z*-s_dPe0qqU}s)!W@;?_0Li=|&Ad@&H+?($!G5&N$_02d1ZgycGV>C`w1s_7g|!XH zv@P(9Zjj@|dKvm&=O9`VJK+N=+Ka(T`S$IKb!^^4G>1)UmZcI9*}Ga^Fp(gLk^KHG zXk^*g2F4JQ{$zz6eH&uv$E4d{|B(dDu6MA+FVrZXlq^!S)OM(zafHJUryyYFOe(FO zHBR>W1-QtZ%Uzb!f&j|sD!;m+`eZHuahL;@KjS&1#8ls=9)B(&w#2EM-)g!_t|xYP zYhWQhrV{*_>rc6x-f34V1}JSP!1?-jx|E@&q`4CmbdHQ+WqfA~^sR zIc*3``ue}&heup8M_zo4O*4qGB`7~>WxE`CKO=g|Kp!?j=f`QDHU;kcA!2p>9T}`K zQ}6e;DXHY25+`7d5EtmiSw}FN?fET?RcaZgfbUzc>X+$%sC4jfeiHMzoI-r@?`L

rem0-x-X5KmIl$dSba@0{8%o)(ivVd=o>Qri`*a z1L@*yM7jxCflggA6;zf!zhN>nwd%2&_$sAm~X`b)65yv(&hO(NS0y| z?6)W{mkVD-j8;WD+mnEzs101E%MVAH(^SeRC%5iRH;xUSV_1fnw7L2u;p^DOTw@THa>|jupo)s7Y_LunKol?c=ziZZbnsEdz z(E}+LuI$MPOzAuwCn!>*K!cOU(#344+$O-qP-W!q;iJCl@?M&;PzEi9ze;!{irU7e zQGXGr0xLQD^y%5zU!{v6;s64dcAVhUC_p0sbpa`=WI*mTLj4{-yq_b6&Q5Z1E^k(f z+|XHAXO)x|;>8M9?m5EFxm|vWRdNGeWQL9?FQ{~md!Ihph)sruggY&k^o_@xYa!k7 zD$!zR<_Qduef@NbE{8IEo~inUB{1~L&ZH#Z+O8I{93ovjDS|;&ALmuqcasSE#T{c$ zeVYp@XC7tOT<0J2*33YCVlyD=dr1wRFMjZ*c%8HGez@I@8DtNYdfzV+k^MCbT^_Nv z+DJBRcJz`$rpSri$?*~5*2}H#`PI#cAMNmt4X{aE0FJM})xdvb>YrQWIC0IQivXop zm-H6s3$&GC2TY#6A)BTyf22wW?}k|h&olFYa7{I%z=3k*W3=w0a14Gt53^imxxIdb zQlxg2{knu28lES)mP0<|kOAd}ucls$3#6spw}tl`<9>S9asu5ZP6(vcH(dI|rCWob zq)5#LfgXaA{+F>=DTz)@iRy@FUM_%#ZJF?OM8v01_twaU_JKgqDjD-m8!zTye%6me z6&C4Slpiqs&o3MK49D+yUsJiHTkw2xv_(S$VCaap~_ybU)zlphq z+(12%^8my&7cIi~GVJmp`$v%oe##V_!jIUDQ+wG>-yT7~XYZR0w9<@4VCX<(_SoT_ zF$Svw?=fhBHHU9Fw+qACg6L#3Jhdc7c*Kxz(9Ir1T(X45j9>8UBy?Zh*Kf^kB$kPB zn!|t3-ac&-9eP`D|HahY0gUAdGykWU0)wD{{+uN!K>6>tDFBVXe)9c(R{!#D#cP1q z+5LZ!0|DjxRRfmfAG!Xo3126{|0e7LtRp}P|BsaT*Ep}!!++zP1HvExoPQ>Zzb1a2 z-Ta%_7O->wCjPHn=hrB&lX`xmw8Fhc`PUSm*MP6{VSWQn12W+MWmv!L+1DtqBg?;0 z#sLEGFDSp_%&$>i2bF%KU}OG5`5j_vc3J^{J zAiNGGyassfqWTRGLHI8YtJmbO-9Ep`U5Nfc{$NB2Hx>=aKe7IU@*3c^Tj4jr#(x3)b~3z1d3}HXjnYc`YeD{b%lf5xUn9J} znf*o}qxdg`f0gUkHui6XkCcBQ{F}x7dK|B9+21IhfL9#=qV=Bx`>*Bs=dt~-EA-lq z{0%5i{U_kRS(UGc_u7K^jaESWC)z&;_8R5&(fAt$iT)SLe;t%^lHd?Od!Yk<2?5`v I7=AweKL}!YH~;_u literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/zavora-xlsx/repeat-2-input.xlsx b/results-2026-09-08/mutation/zavora-xlsx/repeat-2-input.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7 GIT binary patch literal 15042 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/zavora-xlsx/repeat-2-output.xlsx b/results-2026-09-08/mutation/zavora-xlsx/repeat-2-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..14b5814969c508fb9564b36cdff0cc2613da481e GIT binary patch literal 14211 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

rem0-x-X5KmIl$dSba@0{8%o)(ivVd=o>Qri`*a z1L@*yM7jxCflggA6;zf!zhN>nwd%2&_$sAm~X`b)65yv(&hO(NS0y| z?6)W{mkVD-j8;WD+mnEzs101E%MVAH(^SeRC%5iRH;xUSV_1fnw7L2u;p^DOTw@THa>|jupo)s7Y_LunKol?c=ziZZbnsEdz z(E}+LuI$MPOzAuwCn!>*K!cOU(#344+$O-qP-W!q;iJCl@?M&;PzEi9ze;!{irU7e zQGXGr0xLQD^y%5zU!{v6;s64dcAVhUC_p0sbpa`=WI*mTLj4{-yq_b6&Q5Z1E^k(f z+|XHAXO)x|;>8M9?m5EFxm|vWRdNGeWQL9?FQ{~md!Ihph)sruggY&k^o_@xYa!k7 zD$!zR<_Qduef@NbE{8IEo~inUB{1~L&ZH#Z+O8I{93ovjDS|;&ALmuqcasSE#T{c$ zeVYp@XC7tOT<0J2*33YCVlyD=dr1wRFMjZ*c%8HGez@I@8DtNYdfzV+k^MCbT^_Nv z+DJBRcJz`$rpSri$?*~5*2}H#`PI#cAMNmt4X{aE0FJM})xdvb>YrQWIC0IQivXop zm-H6s3$&GC2TY#6A)BTyf22wW?}k|h&olFYa7{I%z=3k*W3=w0a14Gt53^imxxIdb zQlxg2{knu28lES)mP0<|kOAd}ucls$3#6spw}tl`<9>S9asu5ZP6(vcH(dI|rCWob zq)5#LfgXaA{+F>=DTz)@iRy@FUM_%#ZJF?OM8v01_twaU_JKgqDjD-m8!zTye%6me z6&C4Slpiqs&o3MK49D+yUsJiHTkw2xv_(S$VCaap~_ybU)zlphq z+(12%^8my&7cIi~GVJmp`$v%oe##V_!jIUDQ+wG>-yT7~XYZR0w9<@4VCX<(_SoT_ zF$Svw?=fhBHHU9Fw+qACg6L#3Jhdc7c*Kxz(9Ir1T(X45j9>8UBy?Zh*Kf^kB$kPB zn!|t3-ac&-9eP`D|HahY0gUAdGykWU0)wD{{+uN!K>6>tDFBVXe)9c(R{!#D#cP1q z+5LZ!0|DjxRRfmfAG!Xo3126{|0e7LtRp}P|BsaT*Ep}!!++zP1HvExoPQ>Zzb1a2 z-Ta%_7O->wCjPHn=hrB&lX`xmw8Fhc`PUSm*MP6{VSWQn12W+MWmv!L+1DtqBg?;0 z#sLEGFDSp_%&$>i2bF%KU}OG5`5j_vc3J^{J zAiNGGyassfqWTRGLHI8YtJmbO-9Ep`U5Nfc{$NB2Hx>=aKe7IU@*3c^Tj4jr#(x3)b~3z1d3}HXjnYc`YeD{b%lf5xUn9J} znf*o}qxdg`f0gUkHui6XkCcBQ{F}x7dK|B9+21IhfL9#=qV=Bx`>*Bs=dt~-EA-lq z{0%5i{U_kRS(UGc_u7K^jaESWC)z&;_8R5&(fAt$iT)SLe;t%^lHd?Od!Yk<2?5`v I7=AweKL}!YH~;_u literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/zavora-xlsx/repeat-3-input.xlsx b/results-2026-09-08/mutation/zavora-xlsx/repeat-3-input.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7 GIT binary patch literal 15042 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 Jd9(dG`hP@$8FK&t literal 0 HcmV?d00001 diff --git a/results-2026-09-08/mutation/zavora-xlsx/repeat-3-output.xlsx b/results-2026-09-08/mutation/zavora-xlsx/repeat-3-output.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..14b5814969c508fb9564b36cdff0cc2613da481e GIT binary patch literal 14211 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

rem0-x-X5KmIl$dSba@0{8%o)(ivVd=o>Qri`*a z1L@*yM7jxCflggA6;zf!zhN>nwd%2&_$sAm~X`b)65yv(&hO(NS0y| z?6)W{mkVD-j8;WD+mnEzs101E%MVAH(^SeRC%5iRH;xUSV_1fnw7L2u;p^DOTw@THa>|jupo)s7Y_LunKol?c=ziZZbnsEdz z(E}+LuI$MPOzAuwCn!>*K!cOU(#344+$O-qP-W!q;iJCl@?M&;PzEi9ze;!{irU7e zQGXGr0xLQD^y%5zU!{v6;s64dcAVhUC_p0sbpa`=WI*mTLj4{-yq_b6&Q5Z1E^k(f z+|XHAXO)x|;>8M9?m5EFxm|vWRdNGeWQL9?FQ{~md!Ihph)sruggY&k^o_@xYa!k7 zD$!zR<_Qduef@NbE{8IEo~inUB{1~L&ZH#Z+O8I{93ovjDS|;&ALmuqcasSE#T{c$ zeVYp@XC7tOT<0J2*33YCVlyD=dr1wRFMjZ*c%8HGez@I@8DtNYdfzV+k^MCbT^_Nv z+DJBRcJz`$rpSri$?*~5*2}H#`PI#cAMNmt4X{aE0FJM})xdvb>YrQWIC0IQivXop zm-H6s3$&GC2TY#6A)BTyf22wW?}k|h&olFYa7{I%z=3k*W3=w0a14Gt53^imxxIdb zQlxg2{knu28lES)mP0<|kOAd}ucls$3#6spw}tl`<9>S9asu5ZP6(vcH(dI|rCWob zq)5#LfgXaA{+F>=DTz)@iRy@FUM_%#ZJF?OM8v01_twaU_JKgqDjD-m8!zTye%6me z6&C4Slpiqs&o3MK49D+yUsJiHTkw2xv_(S$VCaap~_ybU)zlphq z+(12%^8my&7cIi~GVJmp`$v%oe##V_!jIUDQ+wG>-yT7~XYZR0w9<@4VCX<(_SoT_ zF$Svw?=fhBHHU9Fw+qACg6L#3Jhdc7c*Kxz(9Ir1T(X45j9>8UBy?Zh*Kf^kB$kPB zn!|t3-ac&-9eP`D|HahY0gUAdGykWU0)wD{{+uN!K>6>tDFBVXe)9c(R{!#D#cP1q z+5LZ!0|DjxRRfmfAG!Xo3126{|0e7LtRp}P|BsaT*Ep}!!++zP1HvExoPQ>Zzb1a2 z-Ta%_7O->wCjPHn=hrB&lX`xmw8Fhc`PUSm*MP6{VSWQn12W+MWmv!L+1DtqBg?;0 z#sLEGFDSp_%&$>i2bF%KU}OG5`5j_vc3J^{J zAiNGGyassfqWTRGLHI8YtJmbO-9Ep`U5Nfc{$NB2Hx>=aKe7IU@*3c^Tj4jr#(x3)b~3z1d3}HXjnYc`YeD{b%lf5xUn9J} znf*o}qxdg`f0gUkHui6XkCcBQ{F}x7dK|B9+21IhfL9#=qV=Bx`>*Bs=dt~-EA-lq z{0%5i{U_kRS(UGc_u7K^jaESWC)z&;_8R5&(fAt$iT)SLe;t%^lHd?Od!Yk<2?5`v I7=AweKL}!YH~;_u literal 0 HcmV?d00001 diff --git a/results-2026-09-08/xlsx/FIDELITY_DELTAS.md b/results-2026-09-08/xlsx/FIDELITY_DELTAS.md new file mode 100644 index 0000000..a91d7e9 --- /dev/null +++ b/results-2026-09-08/xlsx/FIDELITY_DELTAS.md @@ -0,0 +1,3 @@ +# Fidelity Deltas + +Need at least two runs in history.jsonl. diff --git a/results-2026-09-08/xlsx/README.md b/results-2026-09-08/xlsx/README.md new file mode 100644 index 0000000..8bcc4d8 --- /dev/null +++ b/results-2026-09-08/xlsx/README.md @@ -0,0 +1,4025 @@ +# ExcelBench Results + +*Generated: 2026-09-08 05:35 UTC* +*Profile: xlsx* +*Excel Version: 16.105.3* +*Platform: Darwin-arm64* + +## Overview + +> Condensed view — shows the **best score** across read/write for each library. See [Full Results Matrix](#full-results-matrix) for the complete R/W breakdown. + +**Tier 0 — Basic Values** + +| Feature | aspose-cells-foss | openpyxl | opxl-readonly | pandas | polars | pyexcel | pylightxl | calamine | tablib | wolfxl | xlsxwriter | xlsx-constmem | xlwt | +|---------|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| +| Cell Values | 🟢 | 🟢 | 🟢 | 🟢 | 🟠 | 🟢 | 🟢 | 🟠 | 🟢 | 🟢 | 🟢 | 🟢 | 🟢 | +| Formulas | 🟢 | 🟢 | 🟢 | 🟢 | 🔴 | 🟢 | 🟢 | 🔴 | 🟢 | 🟢 | 🟢 | 🟢 | 🔴 | +| Sheets | 🟢 | 🟢 | 🟢 | 🟢 | 🟠 | 🟢 | 🟢 | 🟢 | 🟢 | 🟢 | 🟢 | 🟢 | 🟢 | + +**Tier 1 — Formatting** + +| Feature | aspose-cells-foss | openpyxl | opxl-readonly | pandas | polars | pyexcel | pylightxl | calamine | tablib | wolfxl | xlsxwriter | xlsx-constmem | xlwt | +|---------|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| +| Alignment | 🟠 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟠 | 🟠 | 🟢 | +| Bg Colors | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🟢 | 🟠 | +| Borders | 🟠 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🟢 | 🟠 | +| Dimensions | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🟠 | 🟠 | +| Num Fmt | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🟢 | 🟢 | +| Text Fmt | 🟠 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🟢 | 🟠 | + +**Tier 2 — Advanced** + +| Feature | aspose-cells-foss | openpyxl | opxl-readonly | pandas | polars | pyexcel | pylightxl | calamine | tablib | wolfxl | xlsxwriter | xlsx-constmem | xlwt | +|---------|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| +| chart_anchor | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🔴 | 🔴 | 🔴 | +| Comments | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🔴 | 🔴 | +| Cond Fmt | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🟢 | 🔴 | +| Validation | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🟢 | 🔴 | +| Freeze | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🟢 | 🔴 | +| Hyperlinks | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🟢 | 🔴 | +| Images | 🔴 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🔴 | 🔴 | +| Merged | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🟢 | 🟢 | 🔴 | +| page_setup | 🟠 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🔴 | 🔴 | 🔴 | +| sheet_protection | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🔴 | 🔴 | 🔴 | + +**Tier 3 — Workbook Metadata** + +| Feature | aspose-cells-foss | openpyxl | opxl-readonly | pandas | polars | pyexcel | pylightxl | calamine | tablib | wolfxl | xlsxwriter | xlsx-constmem | xlwt | +|---------|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| +| Named Ranges | 🟢 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🔴 | 🔴 | 🔴 | +| Tables | 🟠 | 🟢 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🔴 | 🟢 | 🔴 | 🔴 | 🔴 | + +## Library Tiers + +> Libraries ranked by their best capability (max of read/write green features). + +| Tier | Library | Caps | Modify | Green Features | Summary | +|:----:|---------|:----:|:------:|:--------------:|---------| +| **S** | openpyxl | R+W | Rewrite | 21/21 | Reference adapter — full read + write fidelity | +| **S-** | wolfxl | R+W | Patch | 20/21 | Hybrid Rust+Python — near-full fidelity at 3-9x throughput | +| **A** | xlsxwriter | W | No | 15/21 | Best write-only option — full formatting support | +| **B** | aspose-cells-foss | R+W | Rewrite | 14/21 | 14/21 features with full fidelity | +| **B** | xlsxwriter-constmem | W | No | 12/21 | Memory-optimized write — loses images, comments, row height | +| **B** | xlwt | W | No | 4/21 | Legacy .xls writer — basic formatting subset | +| **C** | openpyxl-readonly | R | No | 3/21 | Streaming read — loses all formatting metadata | +| **C** | pandas | R+W | Rebuild | 3/21 | DataFrame abstraction — errors coerced to NaN on read | +| **C** | tablib | R+W | Rebuild | 3/21 | Dataset wrapper — matches pyexcel on fidelity | +| **C** | pyexcel | R+W | Rebuild | 2/21 | Meta-library wrapping openpyxl — preserves error values | +| **C** | pylightxl | R+W | Rebuild | 2/21 | Lightweight — basic values, no formatting API | +| **C** | python-calamine | R | No | 1/21 | Fast Rust-backed reader — cell values + sheet names only | +| **D** | polars | R | No | 0/21 | Rust DataFrame reader — columnar type coercion drops fidelity | + +## Score Legend + +| Score | Meaning | +|-------|---------| +| 🟢 3 | Complete — all basic and edge cases pass | +| 🟡 2 | Functional — all basic pass, one or more edge cases fail | +| 🟠 1 | Minimal — at least one basic case passes, but not all basic cases | +| 🔴 0 | Unsupported — errors or data loss | +| ➖ | Not applicable | + +## Full Results Matrix + +**Tier 0 — Basic Values** + +| Feature | aspose-cells-foss (R) | aspose-cells-foss (W) | openpyxl (R) | openpyxl (W) | openpyxl-readonly (R) | pandas (R) | pandas (W) | polars (R) | pyexcel (R) | pyexcel (W) | pylightxl (R) | pylightxl (W) | python-calamine (R) | tablib (R) | tablib (W) | wolfxl (R) | wolfxl (W) | xlrd (R) | xlsxwriter (W) | xlsxwriter-constmem (W) | xlwt (W) | +|---------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------| +| [cell_values](#cell_values-details) | 🟠 1 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟠 1 | 🟢 3 | 🟠 1 | 🟢 3 | 🔴 0 | 🟢 3 | 🔴 0 | 🟠 1 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🟢 3 | +| [formulas](#formulas-details) | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🟢 3 | 🔴 0 | 🔴 0 | 🟢 3 | 🔴 0 | 🟢 3 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🔴 0 | +| [multiple_sheets](#multiple_sheets-details) | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟠 1 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🟢 3 | + +**Tier 1 — Formatting** + +| Feature | aspose-cells-foss (R) | aspose-cells-foss (W) | openpyxl (R) | openpyxl (W) | openpyxl-readonly (R) | pandas (R) | pandas (W) | polars (R) | pyexcel (R) | pyexcel (W) | pylightxl (R) | pylightxl (W) | python-calamine (R) | tablib (R) | tablib (W) | wolfxl (R) | wolfxl (W) | xlrd (R) | xlsxwriter (W) | xlsxwriter-constmem (W) | xlwt (W) | +|---------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------| +| [alignment](#alignment-details) | 🟠 1 | 🟠 1 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟠 1 | 🟠 1 | 🟢 3 | +| [background_colors](#background_colors-details) | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🟠 1 | +| [borders](#borders-details) | 🟠 1 | 🟠 1 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🟠 1 | +| [dimensions](#dimensions-details) | 🟠 1 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟠 1 | 🟠 1 | +| [number_formats](#number_formats-details) | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🟢 3 | +| [text_formatting](#text_formatting-details) | 🟠 1 | 🔴 0 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🟠 1 | + +**Tier 2 — Advanced** + +| Feature | aspose-cells-foss (R) | aspose-cells-foss (W) | openpyxl (R) | openpyxl (W) | openpyxl-readonly (R) | pandas (R) | pandas (W) | polars (R) | pyexcel (R) | pyexcel (W) | pylightxl (R) | pylightxl (W) | python-calamine (R) | tablib (R) | tablib (W) | wolfxl (R) | wolfxl (W) | xlrd (R) | xlsxwriter (W) | xlsxwriter-constmem (W) | xlwt (W) | +|---------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------| +| [chart_anchor](#chart_anchor-details) | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🔴 0 | 🔴 0 | 🔴 0 | +| [comments](#comments-details) | 🟢 3 | 🔴 0 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🔴 0 | 🔴 0 | +| [conditional_formatting](#conditional_formatting-details) | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🔴 0 | +| [data_validation](#data_validation-details) | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🔴 0 | +| [freeze_panes](#freeze_panes-details) | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🔴 0 | +| [hyperlinks](#hyperlinks-details) | 🔴 0 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🔴 0 | +| [images](#images-details) | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🔴 0 | 🔴 0 | +| [merged_cells](#merged_cells-details) | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🟢 3 | 🟢 3 | 🔴 0 | +| [page_setup](#page_setup-details) | 🟠 1 | 🔴 0 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟡 2 | ➖ | 🔴 0 | 🔴 0 | 🔴 0 | +| [pivot_tables](#pivot_tables-details) | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ | +| [sheet_protection](#sheet_protection-details) | 🟢 3 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🔴 0 | 🔴 0 | 🔴 0 | + +**Tier 3 — Workbook Metadata** + +| Feature | aspose-cells-foss (R) | aspose-cells-foss (W) | openpyxl (R) | openpyxl (W) | openpyxl-readonly (R) | pandas (R) | pandas (W) | polars (R) | pyexcel (R) | pyexcel (W) | pylightxl (R) | pylightxl (W) | python-calamine (R) | tablib (R) | tablib (W) | wolfxl (R) | wolfxl (W) | xlrd (R) | xlsxwriter (W) | xlsxwriter-constmem (W) | xlwt (W) | +|---------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------| +| [named_ranges](#named_ranges-details) | 🟡 2 | 🟢 3 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟡 2 | ➖ | 🔴 0 | 🔴 0 | 🔴 0 | +| [tables](#tables-details) | 🟠 1 | 🟠 1 | 🟢 3 | 🟢 3 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🔴 0 | 🟢 3 | 🟢 3 | ➖ | 🔴 0 | 🔴 0 | 🔴 0 | + +## Notes + +- **alignment**: Known limitation: pylightxl alignment write is a no-op because the library does not support formatting writes. +- **cell_values**: Known limitation: pylightxl cell-values write has date/boolean/error fidelity limits due to writer encoding behavior. +- **alignment**: Known limitation: python-calamine alignment read is limited because its API does not expose style/alignment metadata. +- **cell_values**: Known limitation: python-calamine can surface formula error cells as blank values in current API responses. +- **cell_values, formulas, ... (22 features)**: Not applicable: xlrd does not support .xlsx input +- **pivot_tables**: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +## Statistics + +| Library | Mode | Tests | Passed | Failed | Pass Rate | Green Features | +|---------|------|-------|--------|--------|-----------|----------------| +| aspose-cells-foss | R | 133 | 113 | 20 | 85% | 11/21 | +| aspose-cells-foss | W | 133 | 101 | 32 | 76% | 14/21 | +| openpyxl | R | 133 | 133 | 0 | 100% | 21/21 | +| openpyxl | W | 133 | 133 | 0 | 100% | 21/21 | +| openpyxl-readonly | R | 133 | 26 | 107 | 20% | 3/21 | +| pandas | R | 133 | 19 | 114 | 14% | 1/21 | +| pandas | W | 133 | 26 | 107 | 20% | 3/21 | +| polars | R | 133 | 17 | 116 | 13% | 0/21 | +| pyexcel | R | 133 | 22 | 111 | 17% | 2/21 | +| pyexcel | W | 133 | 8 | 125 | 6% | 2/21 | +| pylightxl | R | 133 | 22 | 111 | 17% | 2/21 | +| pylightxl | W | 133 | 8 | 125 | 6% | 2/21 | +| python-calamine | R | 133 | 19 | 114 | 14% | 1/21 | +| tablib | R | 133 | 22 | 111 | 17% | 2/21 | +| tablib | W | 133 | 26 | 107 | 20% | 3/21 | +| wolfxl | R | 133 | 129 | 4 | 97% | 20/21 | +| wolfxl | W | 133 | 131 | 2 | 98% | 19/21 | +| xlsxwriter | W | 133 | 112 | 21 | 84% | 15/21 | +| xlsxwriter-constmem | W | 133 | 105 | 28 | 79% | 12/21 | +| xlwt | W | 133 | 72 | 61 | 54% | 4/21 | + +## Libraries Tested + +- **aspose-cells-foss** v26.7.0 (python) - read, write; modify: Rewrite +- **openpyxl** v3.1.5 (python) - read, write; modify: Rewrite +- **openpyxl-readonly** v3.1.5 (python) - read; modify: No +- **pandas** v3.0.0 (python) - read, write; modify: Rebuild +- **polars** v1.38.1 (python) - read; modify: No +- **pyexcel** v0.7.4 (python) - read, write; modify: Rebuild +- **pylightxl** v1.61 (python) - read, write; modify: Rebuild +- **python-calamine** v0.6.1 (python) - read; modify: No +- **tablib** v3.9.0 (python) - read, write; modify: Rebuild +- **wolfxl** v2.1.0 (python) - modify, read, write; modify: Patch +- **xlrd** v2.0.2 (python) - read; modify: No +- **xlsxwriter** v3.2.9 (python) - write; modify: No +- **xlsxwriter-constmem** v3.2.9 (python) - write; modify: No +- **xlwt** v1.3.0 (python) - write; modify: No + +## Diagnostics Summary + +| Group | Value | Count | +|-------|-------|-------| +| category | data_mismatch | 801 | +| category | internal | 31 | +| category | invalid_input | 69 | +| category | unsupported_feature | 515 | +| severity | error | 901 | +| severity | warning | 515 | + +### Diagnostic Details + +| Feature | Library | Test Case | Operation | Category | Severity | Message | +|---------|---------|-----------|-----------|----------|----------|---------| +| cell_values | python-calamine | error_div0 | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'error', 'value': '#DIV/0!'}, actual={'type': 'blank'} | +| cell_values | python-calamine | error_na | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'error', 'value': '#N/A'}, actual={'type': 'blank'} | +| cell_values | python-calamine | error_value | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'error', 'value': '#VALUE!'}, actual={'type': 'blank'} | +| cell_values | aspose-cells-foss | date_standard | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'date', 'value': '2026-02-04'}, actual={'type': 'number', 'value': 46057} | +| cell_values | aspose-cells-foss | datetime | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'datetime', 'value': '2026-02-04T10:30:45'}, actual={'type': 'number', 'value': 46057.43802083333} | +| cell_values | pylightxl | string_simple | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | string_unicode | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | string_empty | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | string_long | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | string_newline | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | number_integer | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | number_float | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | number_negative | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | number_large | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | number_scientific | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | date_standard | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | datetime | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | boolean_true | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | boolean_false | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | error_div0 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | error_na | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | error_value | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pylightxl | blank | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| cell_values | pyexcel | string_simple | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | string_unicode | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | string_empty | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | string_long | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | string_newline | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | number_integer | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | number_float | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | number_negative | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | number_large | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | number_scientific | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | date_standard | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | datetime | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | boolean_true | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | boolean_false | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | error_div0 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | error_na | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | error_value | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pyexcel | blank | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| cell_values | pandas | error_div0 | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'error', 'value': '#DIV/0!'}, actual={'type': 'blank'} | +| cell_values | pandas | error_na | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'error', 'value': '#N/A'}, actual={'type': 'blank'} | +| cell_values | pandas | error_value | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'error', 'value': '#VALUE!'}, actual={'type': 'blank'} | +| cell_values | polars | error_div0 | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'error', 'value': '#DIV/0!'}, actual={'type': 'blank'} | +| cell_values | polars | error_na | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'error', 'value': '#N/A'}, actual={'type': 'blank'} | +| cell_values | polars | error_value | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'error', 'value': '#VALUE!'}, actual={'type': 'blank'} | +| formulas | python-calamine | formula_sum | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | python-calamine | formula_cell_ref | read | internal | error | RuntimeError: Expected formula, got blank | +| formulas | python-calamine | formula_concat | read | internal | error | RuntimeError: Expected formula, got string | +| formulas | python-calamine | formula_cross_sheet | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | pylightxl | formula_sum | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | pylightxl | formula_cell_ref | read | internal | error | RuntimeError: Expected formula, got error | +| formulas | pylightxl | formula_concat | read | internal | error | RuntimeError: Expected formula, got string | +| formulas | pylightxl | formula_cross_sheet | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | pyexcel | formula_sum | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | pyexcel | formula_cell_ref | read | internal | error | RuntimeError: Expected formula, got error | +| formulas | pyexcel | formula_concat | read | internal | error | RuntimeError: Expected formula, got string | +| formulas | pyexcel | formula_cross_sheet | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | xlwt | formula_sum | write | internal | error | RuntimeError: Expected formula, got string | +| formulas | xlwt | formula_cell_ref | write | internal | error | RuntimeError: Expected formula, got string | +| formulas | xlwt | formula_concat | write | internal | error | RuntimeError: Expected formula, got string | +| formulas | xlwt | formula_cross_sheet | write | internal | error | RuntimeError: Expected formula, got string | +| formulas | pandas | formula_sum | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | pandas | formula_cell_ref | read | internal | error | RuntimeError: Expected formula, got blank | +| formulas | pandas | formula_concat | read | internal | error | RuntimeError: Expected formula, got string | +| formulas | pandas | formula_cross_sheet | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | polars | formula_sum | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | polars | formula_cell_ref | read | internal | error | RuntimeError: Expected formula, got blank | +| formulas | polars | formula_concat | read | internal | error | RuntimeError: Expected formula, got string | +| formulas | polars | formula_cross_sheet | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | tablib | formula_sum | read | internal | error | RuntimeError: Expected formula, got number | +| formulas | tablib | formula_cell_ref | read | internal | error | RuntimeError: Expected formula, got error | +| formulas | tablib | formula_concat | read | internal | error | RuntimeError: Expected formula, got string | +| formulas | tablib | formula_cross_sheet | read | internal | error | RuntimeError: Expected formula, got number | +| text_formatting | python-calamine | bold | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True}, actual={} | +| text_formatting | python-calamine | italic | read | data_mismatch | error | Expected values did not match actual values: expected={'italic': True}, actual={} | +| text_formatting | python-calamine | underline_single | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'single'}, actual={} | +| text_formatting | python-calamine | underline_double | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'double'}, actual={} | +| text_formatting | python-calamine | strikethrough | read | data_mismatch | error | Expected values did not match actual values: expected={'strikethrough': True}, actual={} | +| text_formatting | python-calamine | bold_italic | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={} | +| text_formatting | python-calamine | font_size_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 8}, actual={} | +| text_formatting | python-calamine | font_size_14 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 14}, actual={} | +| text_formatting | python-calamine | font_size_24 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 24}, actual={} | +| text_formatting | python-calamine | font_size_36 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 36}, actual={} | +| text_formatting | python-calamine | font_arial | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={} | +| text_formatting | python-calamine | font_times | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={} | +| text_formatting | python-calamine | font_courier | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={} | +| text_formatting | python-calamine | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={} | +| text_formatting | python-calamine | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={} | +| text_formatting | python-calamine | color_green | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={} | +| text_formatting | python-calamine | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={} | +| text_formatting | python-calamine | combined | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={} | +| text_formatting | aspose-cells-foss | underline_double | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'double'}, actual={'underline': 'single', 'font_name': 'Aptos Narrow', 'font_size': 12.0, 'font_color': '#000000'} | +| text_formatting | aspose-cells-foss | bold | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | italic | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | underline_single | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | underline_double | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | strikethrough | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | bold_italic | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | font_size_8 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | font_size_14 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | font_size_24 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | font_size_36 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | font_arial | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | font_times | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | font_courier | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | color_red | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | color_blue | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | color_green | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | color_custom | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | aspose-cells-foss | combined | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants. | +| text_formatting | pylightxl | bold | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True}, actual={} | +| text_formatting | pylightxl | italic | read | data_mismatch | error | Expected values did not match actual values: expected={'italic': True}, actual={} | +| text_formatting | pylightxl | underline_single | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'single'}, actual={} | +| text_formatting | pylightxl | underline_double | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'double'}, actual={} | +| text_formatting | pylightxl | strikethrough | read | data_mismatch | error | Expected values did not match actual values: expected={'strikethrough': True}, actual={} | +| text_formatting | pylightxl | bold_italic | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={} | +| text_formatting | pylightxl | font_size_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 8}, actual={} | +| text_formatting | pylightxl | font_size_14 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 14}, actual={} | +| text_formatting | pylightxl | font_size_24 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 24}, actual={} | +| text_formatting | pylightxl | font_size_36 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 36}, actual={} | +| text_formatting | pylightxl | font_arial | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={} | +| text_formatting | pylightxl | font_times | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={} | +| text_formatting | pylightxl | font_courier | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={} | +| text_formatting | pylightxl | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={} | +| text_formatting | pylightxl | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={} | +| text_formatting | pylightxl | color_green | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={} | +| text_formatting | pylightxl | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={} | +| text_formatting | pylightxl | combined | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={} | +| text_formatting | pylightxl | bold | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | italic | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | underline_single | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | underline_double | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | strikethrough | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | bold_italic | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | font_size_8 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | font_size_14 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | font_size_24 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | font_size_36 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | font_arial | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | font_times | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | font_courier | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | color_red | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | color_blue | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | color_green | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | color_custom | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pylightxl | combined | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| text_formatting | pyexcel | bold | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True}, actual={} | +| text_formatting | pyexcel | italic | read | data_mismatch | error | Expected values did not match actual values: expected={'italic': True}, actual={} | +| text_formatting | pyexcel | underline_single | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'single'}, actual={} | +| text_formatting | pyexcel | underline_double | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'double'}, actual={} | +| text_formatting | pyexcel | strikethrough | read | data_mismatch | error | Expected values did not match actual values: expected={'strikethrough': True}, actual={} | +| text_formatting | pyexcel | bold_italic | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={} | +| text_formatting | pyexcel | font_size_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 8}, actual={} | +| text_formatting | pyexcel | font_size_14 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 14}, actual={} | +| text_formatting | pyexcel | font_size_24 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 24}, actual={} | +| text_formatting | pyexcel | font_size_36 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 36}, actual={} | +| text_formatting | pyexcel | font_arial | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={} | +| text_formatting | pyexcel | font_times | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={} | +| text_formatting | pyexcel | font_courier | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={} | +| text_formatting | pyexcel | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={} | +| text_formatting | pyexcel | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={} | +| text_formatting | pyexcel | color_green | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={} | +| text_formatting | pyexcel | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={} | +| text_formatting | pyexcel | combined | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={} | +| text_formatting | pyexcel | bold | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | italic | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | underline_single | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | underline_double | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | strikethrough | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | bold_italic | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | font_size_8 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | font_size_14 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | font_size_24 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | font_size_36 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | font_arial | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | font_times | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | font_courier | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | color_red | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | color_blue | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | color_green | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | color_custom | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | pyexcel | combined | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| text_formatting | xlwt | color_green | write | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={'font_name': 'Arial', 'font_size': 10.0, 'font_color': '#008000'} | +| text_formatting | xlwt | color_custom | write | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={'font_name': 'Arial', 'font_size': 10.0, 'font_color': '#993300'} | +| text_formatting | pandas | bold | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True}, actual={} | +| text_formatting | pandas | italic | read | data_mismatch | error | Expected values did not match actual values: expected={'italic': True}, actual={} | +| text_formatting | pandas | underline_single | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'single'}, actual={} | +| text_formatting | pandas | underline_double | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'double'}, actual={} | +| text_formatting | pandas | strikethrough | read | data_mismatch | error | Expected values did not match actual values: expected={'strikethrough': True}, actual={} | +| text_formatting | pandas | bold_italic | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={} | +| text_formatting | pandas | font_size_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 8}, actual={} | +| text_formatting | pandas | font_size_14 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 14}, actual={} | +| text_formatting | pandas | font_size_24 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 24}, actual={} | +| text_formatting | pandas | font_size_36 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 36}, actual={} | +| text_formatting | pandas | font_arial | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={} | +| text_formatting | pandas | font_times | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={} | +| text_formatting | pandas | font_courier | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={} | +| text_formatting | pandas | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={} | +| text_formatting | pandas | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={} | +| text_formatting | pandas | color_green | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={} | +| text_formatting | pandas | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={} | +| text_formatting | pandas | combined | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={} | +| text_formatting | pandas | bold | write | data_mismatch | error | Expected values did not match actual values: expected={'bold': True}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | italic | write | data_mismatch | error | Expected values did not match actual values: expected={'italic': True}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | underline_single | write | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'single'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | underline_double | write | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'double'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | strikethrough | write | data_mismatch | error | Expected values did not match actual values: expected={'strikethrough': True}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | bold_italic | write | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | font_size_8 | write | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 8}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | font_size_14 | write | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 14}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | font_size_24 | write | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 24}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | font_size_36 | write | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 36}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | font_arial | write | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | font_times | write | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | font_courier | write | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | color_red | write | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | color_blue | write | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | color_green | write | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | color_custom | write | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | pandas | combined | write | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | openpyxl-readonly | bold | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True}, actual={} | +| text_formatting | openpyxl-readonly | italic | read | data_mismatch | error | Expected values did not match actual values: expected={'italic': True}, actual={} | +| text_formatting | openpyxl-readonly | underline_single | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'single'}, actual={} | +| text_formatting | openpyxl-readonly | underline_double | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'double'}, actual={} | +| text_formatting | openpyxl-readonly | strikethrough | read | data_mismatch | error | Expected values did not match actual values: expected={'strikethrough': True}, actual={} | +| text_formatting | openpyxl-readonly | bold_italic | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={} | +| text_formatting | openpyxl-readonly | font_size_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 8}, actual={} | +| text_formatting | openpyxl-readonly | font_size_14 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 14}, actual={} | +| text_formatting | openpyxl-readonly | font_size_24 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 24}, actual={} | +| text_formatting | openpyxl-readonly | font_size_36 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 36}, actual={} | +| text_formatting | openpyxl-readonly | font_arial | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={} | +| text_formatting | openpyxl-readonly | font_times | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={} | +| text_formatting | openpyxl-readonly | font_courier | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={} | +| text_formatting | openpyxl-readonly | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={} | +| text_formatting | openpyxl-readonly | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={} | +| text_formatting | openpyxl-readonly | color_green | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={} | +| text_formatting | openpyxl-readonly | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={} | +| text_formatting | openpyxl-readonly | combined | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={} | +| text_formatting | polars | bold | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True}, actual={} | +| text_formatting | polars | italic | read | data_mismatch | error | Expected values did not match actual values: expected={'italic': True}, actual={} | +| text_formatting | polars | underline_single | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'single'}, actual={} | +| text_formatting | polars | underline_double | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'double'}, actual={} | +| text_formatting | polars | strikethrough | read | data_mismatch | error | Expected values did not match actual values: expected={'strikethrough': True}, actual={} | +| text_formatting | polars | bold_italic | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={} | +| text_formatting | polars | font_size_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 8}, actual={} | +| text_formatting | polars | font_size_14 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 14}, actual={} | +| text_formatting | polars | font_size_24 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 24}, actual={} | +| text_formatting | polars | font_size_36 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 36}, actual={} | +| text_formatting | polars | font_arial | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={} | +| text_formatting | polars | font_times | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={} | +| text_formatting | polars | font_courier | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={} | +| text_formatting | polars | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={} | +| text_formatting | polars | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={} | +| text_formatting | polars | color_green | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={} | +| text_formatting | polars | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={} | +| text_formatting | polars | combined | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={} | +| text_formatting | tablib | bold | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True}, actual={} | +| text_formatting | tablib | italic | read | data_mismatch | error | Expected values did not match actual values: expected={'italic': True}, actual={} | +| text_formatting | tablib | underline_single | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'single'}, actual={} | +| text_formatting | tablib | underline_double | read | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'double'}, actual={} | +| text_formatting | tablib | strikethrough | read | data_mismatch | error | Expected values did not match actual values: expected={'strikethrough': True}, actual={} | +| text_formatting | tablib | bold_italic | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={} | +| text_formatting | tablib | font_size_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 8}, actual={} | +| text_formatting | tablib | font_size_14 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 14}, actual={} | +| text_formatting | tablib | font_size_24 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 24}, actual={} | +| text_formatting | tablib | font_size_36 | read | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 36}, actual={} | +| text_formatting | tablib | font_arial | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={} | +| text_formatting | tablib | font_times | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={} | +| text_formatting | tablib | font_courier | read | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={} | +| text_formatting | tablib | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={} | +| text_formatting | tablib | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={} | +| text_formatting | tablib | color_green | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={} | +| text_formatting | tablib | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={} | +| text_formatting | tablib | combined | read | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={} | +| text_formatting | tablib | bold | write | data_mismatch | error | Expected values did not match actual values: expected={'bold': True}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | italic | write | data_mismatch | error | Expected values did not match actual values: expected={'italic': True}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | underline_single | write | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'single'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | underline_double | write | data_mismatch | error | Expected values did not match actual values: expected={'underline': 'double'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | strikethrough | write | data_mismatch | error | Expected values did not match actual values: expected={'strikethrough': True}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | bold_italic | write | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | font_size_8 | write | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 8}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | font_size_14 | write | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 14}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | font_size_24 | write | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 24}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | font_size_36 | write | data_mismatch | error | Expected values did not match actual values: expected={'font_size': 36}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | font_arial | write | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | font_times | write | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | font_courier | write | data_mismatch | error | Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | color_red | write | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | color_blue | write | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | color_green | write | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | color_custom | write | data_mismatch | error | Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| text_formatting | tablib | combined | write | data_mismatch | error | Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={'font_name': 'Calibri', 'font_size': 11.0} | +| background_colors | python-calamine | bg_red | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={} | +| background_colors | python-calamine | bg_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={} | +| background_colors | python-calamine | bg_green | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={} | +| background_colors | python-calamine | bg_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={} | +| background_colors | pylightxl | bg_red | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={} | +| background_colors | pylightxl | bg_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={} | +| background_colors | pylightxl | bg_green | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={} | +| background_colors | pylightxl | bg_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={} | +| background_colors | pylightxl | bg_red | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| background_colors | pylightxl | bg_blue | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| background_colors | pylightxl | bg_green | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| background_colors | pylightxl | bg_custom | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| background_colors | pyexcel | bg_red | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={} | +| background_colors | pyexcel | bg_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={} | +| background_colors | pyexcel | bg_green | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={} | +| background_colors | pyexcel | bg_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={} | +| background_colors | pyexcel | bg_red | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| background_colors | pyexcel | bg_blue | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| background_colors | pyexcel | bg_green | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| background_colors | pyexcel | bg_custom | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| background_colors | xlwt | bg_green | write | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={'bg_color': '#008000'} | +| background_colors | xlwt | bg_custom | write | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={'bg_color': '#993300'} | +| background_colors | pandas | bg_red | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={} | +| background_colors | pandas | bg_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={} | +| background_colors | pandas | bg_green | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={} | +| background_colors | pandas | bg_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={} | +| background_colors | pandas | bg_red | write | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={} | +| background_colors | pandas | bg_blue | write | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={} | +| background_colors | pandas | bg_green | write | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={} | +| background_colors | pandas | bg_custom | write | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={} | +| background_colors | openpyxl-readonly | bg_red | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={} | +| background_colors | openpyxl-readonly | bg_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={} | +| background_colors | openpyxl-readonly | bg_green | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={} | +| background_colors | openpyxl-readonly | bg_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={} | +| background_colors | polars | bg_red | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={} | +| background_colors | polars | bg_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={} | +| background_colors | polars | bg_green | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={} | +| background_colors | polars | bg_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={} | +| background_colors | tablib | bg_red | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={} | +| background_colors | tablib | bg_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={} | +| background_colors | tablib | bg_green | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={} | +| background_colors | tablib | bg_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={} | +| background_colors | tablib | bg_red | write | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={} | +| background_colors | tablib | bg_blue | write | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={} | +| background_colors | tablib | bg_green | write | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={} | +| background_colors | tablib | bg_custom | write | data_mismatch | error | Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={} | +| number_formats | python-calamine | numfmt_currency | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={} | +| number_formats | python-calamine | numfmt_percent | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={} | +| number_formats | python-calamine | numfmt_date | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={} | +| number_formats | python-calamine | numfmt_scientific | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={} | +| number_formats | python-calamine | numfmt_custom_text | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '"USD" 0.00'}, actual={} | +| number_formats | pylightxl | numfmt_currency | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={} | +| number_formats | pylightxl | numfmt_percent | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={} | +| number_formats | pylightxl | numfmt_date | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={} | +| number_formats | pylightxl | numfmt_scientific | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={} | +| number_formats | pylightxl | numfmt_custom_text | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '"USD" 0.00'}, actual={} | +| number_formats | pylightxl | numfmt_currency | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| number_formats | pylightxl | numfmt_percent | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| number_formats | pylightxl | numfmt_date | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| number_formats | pylightxl | numfmt_scientific | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| number_formats | pylightxl | numfmt_custom_text | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| number_formats | pyexcel | numfmt_currency | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={} | +| number_formats | pyexcel | numfmt_percent | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={} | +| number_formats | pyexcel | numfmt_date | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={} | +| number_formats | pyexcel | numfmt_scientific | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={} | +| number_formats | pyexcel | numfmt_custom_text | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '"USD" 0.00'}, actual={} | +| number_formats | pyexcel | numfmt_currency | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| number_formats | pyexcel | numfmt_percent | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| number_formats | pyexcel | numfmt_date | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| number_formats | pyexcel | numfmt_scientific | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| number_formats | pyexcel | numfmt_custom_text | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| number_formats | pandas | numfmt_currency | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={} | +| number_formats | pandas | numfmt_percent | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={} | +| number_formats | pandas | numfmt_date | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={} | +| number_formats | pandas | numfmt_scientific | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={} | +| number_formats | pandas | numfmt_custom_text | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '"USD" 0.00'}, actual={} | +| number_formats | pandas | numfmt_currency | write | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={'number_format': 'General'} | +| number_formats | pandas | numfmt_percent | write | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={'number_format': 'General'} | +| number_formats | pandas | numfmt_date | write | data_mismatch | error | Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={'number_format': 'General'} | +| number_formats | pandas | numfmt_scientific | write | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={'number_format': 'General'} | +| number_formats | pandas | numfmt_custom_text | write | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '"USD" 0.00'}, actual={'number_format': 'General'} | +| number_formats | openpyxl-readonly | numfmt_currency | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={} | +| number_formats | openpyxl-readonly | numfmt_percent | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={} | +| number_formats | openpyxl-readonly | numfmt_date | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={} | +| number_formats | openpyxl-readonly | numfmt_scientific | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={} | +| number_formats | openpyxl-readonly | numfmt_custom_text | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '"USD" 0.00'}, actual={} | +| number_formats | polars | numfmt_currency | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={} | +| number_formats | polars | numfmt_percent | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={} | +| number_formats | polars | numfmt_date | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={} | +| number_formats | polars | numfmt_scientific | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={} | +| number_formats | polars | numfmt_custom_text | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '"USD" 0.00'}, actual={} | +| number_formats | tablib | numfmt_currency | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={} | +| number_formats | tablib | numfmt_percent | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={} | +| number_formats | tablib | numfmt_date | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={} | +| number_formats | tablib | numfmt_scientific | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={} | +| number_formats | tablib | numfmt_custom_text | read | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '"USD" 0.00'}, actual={} | +| number_formats | tablib | numfmt_currency | write | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={'number_format': 'General'} | +| number_formats | tablib | numfmt_percent | write | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={'number_format': 'General'} | +| number_formats | tablib | numfmt_date | write | data_mismatch | error | Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={'number_format': 'General'} | +| number_formats | tablib | numfmt_scientific | write | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={'number_format': 'General'} | +| number_formats | tablib | numfmt_custom_text | write | data_mismatch | error | Expected values did not match actual values: expected={'number_format': '"USD" 0.00'}, actual={'number_format': 'General'} | +| alignment | xlsxwriter | v_bottom | write | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | python-calamine | h_left | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'left'}, actual={} | +| alignment | python-calamine | h_center | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'center'}, actual={} | +| alignment | python-calamine | h_right | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'right'}, actual={} | +| alignment | python-calamine | v_top | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'top'}, actual={} | +| alignment | python-calamine | v_center | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'center'}, actual={} | +| alignment | python-calamine | v_bottom | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | python-calamine | wrap_text | read | data_mismatch | error | Expected values did not match actual values: expected={'wrap': True}, actual={} | +| alignment | python-calamine | rotation_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'rotation': 45}, actual={} | +| alignment | python-calamine | indent_2 | read | data_mismatch | error | Expected values did not match actual values: expected={'indent': 2}, actual={} | +| alignment | aspose-cells-foss | v_bottom | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | aspose-cells-foss | v_bottom | write | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | pylightxl | h_left | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| alignment | pylightxl | h_center | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| alignment | pylightxl | h_right | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| alignment | pylightxl | v_top | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| alignment | pylightxl | v_center | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| alignment | pylightxl | v_bottom | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| alignment | pylightxl | wrap_text | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| alignment | pylightxl | rotation_45 | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| alignment | pylightxl | indent_2 | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| alignment | pylightxl | h_left | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| alignment | pylightxl | h_center | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| alignment | pylightxl | h_right | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| alignment | pylightxl | v_top | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| alignment | pylightxl | v_center | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| alignment | pylightxl | v_bottom | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| alignment | pylightxl | wrap_text | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| alignment | pylightxl | rotation_45 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| alignment | pylightxl | indent_2 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature | +| alignment | pyexcel | h_left | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'left'}, actual={} | +| alignment | pyexcel | h_center | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'center'}, actual={} | +| alignment | pyexcel | h_right | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'right'}, actual={} | +| alignment | pyexcel | v_top | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'top'}, actual={} | +| alignment | pyexcel | v_center | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'center'}, actual={} | +| alignment | pyexcel | v_bottom | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | pyexcel | wrap_text | read | data_mismatch | error | Expected values did not match actual values: expected={'wrap': True}, actual={} | +| alignment | pyexcel | rotation_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'rotation': 45}, actual={} | +| alignment | pyexcel | indent_2 | read | data_mismatch | error | Expected values did not match actual values: expected={'indent': 2}, actual={} | +| alignment | pyexcel | h_left | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| alignment | pyexcel | h_center | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| alignment | pyexcel | h_right | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| alignment | pyexcel | v_top | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| alignment | pyexcel | v_center | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| alignment | pyexcel | v_bottom | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| alignment | pyexcel | wrap_text | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| alignment | pyexcel | rotation_45 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| alignment | pyexcel | indent_2 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells | +| alignment | pandas | h_left | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'left'}, actual={} | +| alignment | pandas | h_center | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'center'}, actual={} | +| alignment | pandas | h_right | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'right'}, actual={} | +| alignment | pandas | v_top | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'top'}, actual={} | +| alignment | pandas | v_center | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'center'}, actual={} | +| alignment | pandas | v_bottom | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | pandas | wrap_text | read | data_mismatch | error | Expected values did not match actual values: expected={'wrap': True}, actual={} | +| alignment | pandas | rotation_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'rotation': 45}, actual={} | +| alignment | pandas | indent_2 | read | data_mismatch | error | Expected values did not match actual values: expected={'indent': 2}, actual={} | +| alignment | pandas | h_left | write | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'left'}, actual={} | +| alignment | pandas | h_center | write | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'center'}, actual={} | +| alignment | pandas | h_right | write | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'right'}, actual={} | +| alignment | pandas | v_top | write | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'top'}, actual={} | +| alignment | pandas | v_center | write | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'center'}, actual={} | +| alignment | pandas | v_bottom | write | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | pandas | wrap_text | write | data_mismatch | error | Expected values did not match actual values: expected={'wrap': True}, actual={} | +| alignment | pandas | rotation_45 | write | data_mismatch | error | Expected values did not match actual values: expected={'rotation': 45}, actual={} | +| alignment | pandas | indent_2 | write | data_mismatch | error | Expected values did not match actual values: expected={'indent': 2}, actual={} | +| alignment | xlsxwriter-constmem | v_bottom | write | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | openpyxl-readonly | h_left | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'left'}, actual={} | +| alignment | openpyxl-readonly | h_center | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'center'}, actual={} | +| alignment | openpyxl-readonly | h_right | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'right'}, actual={} | +| alignment | openpyxl-readonly | v_top | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'top'}, actual={} | +| alignment | openpyxl-readonly | v_center | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'center'}, actual={} | +| alignment | openpyxl-readonly | v_bottom | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | openpyxl-readonly | wrap_text | read | data_mismatch | error | Expected values did not match actual values: expected={'wrap': True}, actual={} | +| alignment | openpyxl-readonly | rotation_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'rotation': 45}, actual={} | +| alignment | openpyxl-readonly | indent_2 | read | data_mismatch | error | Expected values did not match actual values: expected={'indent': 2}, actual={} | +| alignment | polars | h_left | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'left'}, actual={} | +| alignment | polars | h_center | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'center'}, actual={} | +| alignment | polars | h_right | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'right'}, actual={} | +| alignment | polars | v_top | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'top'}, actual={} | +| alignment | polars | v_center | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'center'}, actual={} | +| alignment | polars | v_bottom | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | polars | wrap_text | read | data_mismatch | error | Expected values did not match actual values: expected={'wrap': True}, actual={} | +| alignment | polars | rotation_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'rotation': 45}, actual={} | +| alignment | polars | indent_2 | read | data_mismatch | error | Expected values did not match actual values: expected={'indent': 2}, actual={} | +| alignment | tablib | h_left | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'left'}, actual={} | +| alignment | tablib | h_center | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'center'}, actual={} | +| alignment | tablib | h_right | read | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'right'}, actual={} | +| alignment | tablib | v_top | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'top'}, actual={} | +| alignment | tablib | v_center | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'center'}, actual={} | +| alignment | tablib | v_bottom | read | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | tablib | wrap_text | read | data_mismatch | error | Expected values did not match actual values: expected={'wrap': True}, actual={} | +| alignment | tablib | rotation_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'rotation': 45}, actual={} | +| alignment | tablib | indent_2 | read | data_mismatch | error | Expected values did not match actual values: expected={'indent': 2}, actual={} | +| alignment | tablib | h_left | write | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'left'}, actual={} | +| alignment | tablib | h_center | write | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'center'}, actual={} | +| alignment | tablib | h_right | write | data_mismatch | error | Expected values did not match actual values: expected={'h_align': 'right'}, actual={} | +| alignment | tablib | v_top | write | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'top'}, actual={} | +| alignment | tablib | v_center | write | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'center'}, actual={} | +| alignment | tablib | v_bottom | write | data_mismatch | error | Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={} | +| alignment | tablib | wrap_text | write | data_mismatch | error | Expected values did not match actual values: expected={'wrap': True}, actual={} | +| alignment | tablib | rotation_45 | write | data_mismatch | error | Expected values did not match actual values: expected={'rotation': 45}, actual={} | +| alignment | tablib | indent_2 | write | data_mismatch | error | Expected values did not match actual values: expected={'indent': 2}, actual={} | +| borders | python-calamine | thin_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={} | +| borders | python-calamine | medium_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={} | +| borders | python-calamine | thick_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={} | +| borders | python-calamine | double | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={} | +| borders | python-calamine | dashed | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={} | +| borders | python-calamine | dotted | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={} | +| borders | python-calamine | dash_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={} | +| borders | python-calamine | dash_dot_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={} | +| borders | python-calamine | top_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={} | +| borders | python-calamine | bottom_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={} | +| borders | python-calamine | left_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={} | +| borders | python-calamine | right_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={} | +| borders | python-calamine | diagonal_up | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={} | +| borders | python-calamine | diagonal_down | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={} | +| borders | python-calamine | diagonal_both | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={} | +| borders | python-calamine | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={} | +| borders | python-calamine | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={} | +| borders | python-calamine | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={} | +| borders | python-calamine | mixed_styles | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={} | +| borders | python-calamine | mixed_colors | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={} | +| borders | aspose-cells-foss | diagonal_up | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={} | +| borders | aspose-cells-foss | diagonal_down | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={} | +| borders | aspose-cells-foss | diagonal_both | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={} | +| borders | aspose-cells-foss | diagonal_up | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={} | +| borders | aspose-cells-foss | diagonal_down | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={} | +| borders | aspose-cells-foss | diagonal_both | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={} | +| borders | pylightxl | thin_all | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | medium_all | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | thick_all | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | double | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | dashed | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | dotted | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | dash_dot | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | dash_dot_dot | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | top_only | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | bottom_only | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | left_only | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | right_only | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | diagonal_up | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | diagonal_down | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | diagonal_both | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | color_red | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | color_blue | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | color_custom | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | mixed_styles | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | mixed_colors | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| borders | pylightxl | thin_all | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | medium_all | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | thick_all | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | double | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | dashed | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | dotted | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | dash_dot | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | dash_dot_dot | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | top_only | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | bottom_only | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | left_only | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | right_only | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | diagonal_up | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | diagonal_down | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | diagonal_both | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | color_red | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | color_blue | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | color_custom | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | mixed_styles | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pylightxl | mixed_colors | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature | +| borders | pyexcel | thin_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={} | +| borders | pyexcel | medium_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={} | +| borders | pyexcel | thick_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={} | +| borders | pyexcel | double | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={} | +| borders | pyexcel | dashed | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={} | +| borders | pyexcel | dotted | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={} | +| borders | pyexcel | dash_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={} | +| borders | pyexcel | dash_dot_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={} | +| borders | pyexcel | top_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={} | +| borders | pyexcel | bottom_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={} | +| borders | pyexcel | left_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={} | +| borders | pyexcel | right_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={} | +| borders | pyexcel | diagonal_up | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={} | +| borders | pyexcel | diagonal_down | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={} | +| borders | pyexcel | diagonal_both | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={} | +| borders | pyexcel | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={} | +| borders | pyexcel | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={} | +| borders | pyexcel | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={} | +| borders | pyexcel | mixed_styles | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={} | +| borders | pyexcel | mixed_colors | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={} | +| borders | pyexcel | thin_all | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | medium_all | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | thick_all | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | double | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | dashed | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | dotted | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | dash_dot | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | dash_dot_dot | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | top_only | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | bottom_only | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | left_only | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | right_only | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | diagonal_up | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | diagonal_down | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | diagonal_both | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | color_red | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | color_blue | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | color_custom | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | mixed_styles | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | pyexcel | mixed_colors | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells | +| borders | xlwt | diagonal_up | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={'border_diagonal_down': 'thin'} | +| borders | xlwt | diagonal_down | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={'border_diagonal_up': 'thin'} | +| borders | xlwt | color_custom | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={'border_style': 'thin', 'border_color': '#993300'} | +| borders | xlwt | mixed_colors | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={'border_top_color': '#FF0000', 'border_bottom_color': '#008000', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00', 'border_style': 'thin'} | +| borders | pandas | thin_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={} | +| borders | pandas | medium_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={} | +| borders | pandas | thick_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={} | +| borders | pandas | double | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={} | +| borders | pandas | dashed | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={} | +| borders | pandas | dotted | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={} | +| borders | pandas | dash_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={} | +| borders | pandas | dash_dot_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={} | +| borders | pandas | top_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={} | +| borders | pandas | bottom_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={} | +| borders | pandas | left_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={} | +| borders | pandas | right_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={} | +| borders | pandas | diagonal_up | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={} | +| borders | pandas | diagonal_down | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={} | +| borders | pandas | diagonal_both | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={} | +| borders | pandas | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={} | +| borders | pandas | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={} | +| borders | pandas | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={} | +| borders | pandas | mixed_styles | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={} | +| borders | pandas | mixed_colors | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={} | +| borders | pandas | thin_all | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={} | +| borders | pandas | medium_all | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={} | +| borders | pandas | thick_all | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={} | +| borders | pandas | double | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={} | +| borders | pandas | dashed | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={} | +| borders | pandas | dotted | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={} | +| borders | pandas | dash_dot | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={} | +| borders | pandas | dash_dot_dot | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={} | +| borders | pandas | top_only | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={} | +| borders | pandas | bottom_only | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={} | +| borders | pandas | left_only | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={} | +| borders | pandas | right_only | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={} | +| borders | pandas | diagonal_up | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={} | +| borders | pandas | diagonal_down | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={} | +| borders | pandas | diagonal_both | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={} | +| borders | pandas | color_red | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={} | +| borders | pandas | color_blue | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={} | +| borders | pandas | color_custom | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={} | +| borders | pandas | mixed_styles | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={} | +| borders | pandas | mixed_colors | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={} | +| borders | openpyxl-readonly | thin_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={} | +| borders | openpyxl-readonly | medium_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={} | +| borders | openpyxl-readonly | thick_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={} | +| borders | openpyxl-readonly | double | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={} | +| borders | openpyxl-readonly | dashed | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={} | +| borders | openpyxl-readonly | dotted | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={} | +| borders | openpyxl-readonly | dash_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={} | +| borders | openpyxl-readonly | dash_dot_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={} | +| borders | openpyxl-readonly | top_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={} | +| borders | openpyxl-readonly | bottom_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={} | +| borders | openpyxl-readonly | left_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={} | +| borders | openpyxl-readonly | right_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={} | +| borders | openpyxl-readonly | diagonal_up | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={} | +| borders | openpyxl-readonly | diagonal_down | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={} | +| borders | openpyxl-readonly | diagonal_both | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={} | +| borders | openpyxl-readonly | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={} | +| borders | openpyxl-readonly | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={} | +| borders | openpyxl-readonly | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={} | +| borders | openpyxl-readonly | mixed_styles | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={} | +| borders | openpyxl-readonly | mixed_colors | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={} | +| borders | polars | thin_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={} | +| borders | polars | medium_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={} | +| borders | polars | thick_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={} | +| borders | polars | double | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={} | +| borders | polars | dashed | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={} | +| borders | polars | dotted | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={} | +| borders | polars | dash_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={} | +| borders | polars | dash_dot_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={} | +| borders | polars | top_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={} | +| borders | polars | bottom_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={} | +| borders | polars | left_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={} | +| borders | polars | right_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={} | +| borders | polars | diagonal_up | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={} | +| borders | polars | diagonal_down | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={} | +| borders | polars | diagonal_both | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={} | +| borders | polars | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={} | +| borders | polars | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={} | +| borders | polars | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={} | +| borders | polars | mixed_styles | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={} | +| borders | polars | mixed_colors | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={} | +| borders | tablib | thin_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={} | +| borders | tablib | medium_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={} | +| borders | tablib | thick_all | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={} | +| borders | tablib | double | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={} | +| borders | tablib | dashed | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={} | +| borders | tablib | dotted | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={} | +| borders | tablib | dash_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={} | +| borders | tablib | dash_dot_dot | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={} | +| borders | tablib | top_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={} | +| borders | tablib | bottom_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={} | +| borders | tablib | left_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={} | +| borders | tablib | right_only | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={} | +| borders | tablib | diagonal_up | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={} | +| borders | tablib | diagonal_down | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={} | +| borders | tablib | diagonal_both | read | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={} | +| borders | tablib | color_red | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={} | +| borders | tablib | color_blue | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={} | +| borders | tablib | color_custom | read | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={} | +| borders | tablib | mixed_styles | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={} | +| borders | tablib | mixed_colors | read | data_mismatch | error | Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={} | +| borders | tablib | thin_all | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={} | +| borders | tablib | medium_all | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={} | +| borders | tablib | thick_all | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={} | +| borders | tablib | double | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={} | +| borders | tablib | dashed | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={} | +| borders | tablib | dotted | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={} | +| borders | tablib | dash_dot | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={} | +| borders | tablib | dash_dot_dot | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={} | +| borders | tablib | top_only | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={} | +| borders | tablib | bottom_only | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={} | +| borders | tablib | left_only | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={} | +| borders | tablib | right_only | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={} | +| borders | tablib | diagonal_up | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={} | +| borders | tablib | diagonal_down | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={} | +| borders | tablib | diagonal_both | write | data_mismatch | error | Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={} | +| borders | tablib | color_red | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={} | +| borders | tablib | color_blue | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={} | +| borders | tablib | color_custom | write | data_mismatch | error | Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={} | +| borders | tablib | mixed_styles | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={} | +| borders | tablib | mixed_colors | write | data_mismatch | error | Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={} | +| dimensions | python-calamine | row_height_30 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | python-calamine | row_height_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | python-calamine | col_width_20 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None} | +| dimensions | python-calamine | col_width_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None} | +| dimensions | aspose-cells-foss | col_width_20 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': 20.83203125} | +| dimensions | aspose-cells-foss | col_width_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': 8.83203125} | +| dimensions | pylightxl | row_height_30 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | pylightxl | row_height_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | pylightxl | col_width_20 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None} | +| dimensions | pylightxl | col_width_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None} | +| dimensions | pylightxl | row_height_30 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support set_row_height: pylightxl does not implement this feature | +| dimensions | pylightxl | row_height_45 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support set_row_height: pylightxl does not implement this feature | +| dimensions | pylightxl | col_width_20 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support set_row_height: pylightxl does not implement this feature | +| dimensions | pylightxl | col_width_8 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support set_row_height: pylightxl does not implement this feature | +| dimensions | pyexcel | row_height_30 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | pyexcel | row_height_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | pyexcel | col_width_20 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None} | +| dimensions | pyexcel | col_width_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None} | +| dimensions | pyexcel | row_height_30 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support set_row_height: pyexcel does not expose row dimension writing | +| dimensions | pyexcel | row_height_45 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support set_row_height: pyexcel does not expose row dimension writing | +| dimensions | pyexcel | col_width_20 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support set_row_height: pyexcel does not expose row dimension writing | +| dimensions | pyexcel | col_width_8 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support set_row_height: pyexcel does not expose row dimension writing | +| dimensions | xlwt | row_height_30 | write | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | xlwt | row_height_45 | write | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | pandas | row_height_30 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | pandas | row_height_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | pandas | col_width_20 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None} | +| dimensions | pandas | col_width_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None} | +| dimensions | pandas | row_height_30 | write | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | pandas | row_height_45 | write | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | pandas | col_width_20 | write | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': 13.0} | +| dimensions | pandas | col_width_8 | write | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': 13.0} | +| dimensions | xlsxwriter-constmem | row_height_30 | write | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | xlsxwriter-constmem | row_height_45 | write | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | openpyxl-readonly | row_height_30 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | openpyxl-readonly | row_height_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | openpyxl-readonly | col_width_20 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None} | +| dimensions | openpyxl-readonly | col_width_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None} | +| dimensions | polars | row_height_30 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | polars | row_height_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | polars | col_width_20 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None} | +| dimensions | polars | col_width_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None} | +| dimensions | tablib | row_height_30 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | tablib | row_height_45 | read | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | tablib | col_width_20 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None} | +| dimensions | tablib | col_width_8 | read | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None} | +| dimensions | tablib | row_height_30 | write | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None} | +| dimensions | tablib | row_height_45 | write | data_mismatch | error | Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None} | +| dimensions | tablib | col_width_20 | write | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': 13.0} | +| dimensions | tablib | col_width_8 | write | data_mismatch | error | Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': 13.0} | +| multiple_sheets | polars | value_beta | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'string', 'value': 'Beta'}, actual={'type': 'blank'} | +| multiple_sheets | polars | value_gamma | read | data_mismatch | error | Expected values did not match actual values: expected={'type': 'string', 'value': 'Gamma'}, actual={'type': 'blank'} | +| merged_cells | python-calamine | merge_horizontal | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None} | +| merged_cells | python-calamine | merge_vertical | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None} | +| merged_cells | python-calamine | merge_value_off_top_left | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None} | +| merged_cells | python-calamine | merge_top_left_fill | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None} | +| merged_cells | pylightxl | merge_horizontal | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None} | +| merged_cells | pylightxl | merge_vertical | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None} | +| merged_cells | pylightxl | merge_value_off_top_left | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None} | +| merged_cells | pylightxl | merge_top_left_fill | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None} | +| merged_cells | pylightxl | merge_horizontal | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support merge_cells: pylightxl does not implement this feature | +| merged_cells | pylightxl | merge_vertical | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support merge_cells: pylightxl does not implement this feature | +| merged_cells | pylightxl | merge_value_off_top_left | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support merge_cells: pylightxl does not implement this feature | +| merged_cells | pylightxl | merge_top_left_fill | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support merge_cells: pylightxl does not implement this feature | +| merged_cells | pyexcel | merge_horizontal | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None} | +| merged_cells | pyexcel | merge_vertical | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None} | +| merged_cells | pyexcel | merge_value_off_top_left | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None} | +| merged_cells | pyexcel | merge_top_left_fill | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None} | +| merged_cells | pyexcel | merge_horizontal | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature | +| merged_cells | pyexcel | merge_vertical | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature | +| merged_cells | pyexcel | merge_value_off_top_left | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature | +| merged_cells | pyexcel | merge_top_left_fill | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature | +| merged_cells | xlwt | merge_horizontal | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': 'B2:D2', 'top_left_value': None} | +| merged_cells | xlwt | merge_vertical | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': 'B3:B5', 'top_left_value': None} | +| merged_cells | xlwt | merge_value_off_top_left | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': 'B6:D6', 'top_left_value': None, 'non_top_left_nonempty': 0} | +| merged_cells | xlwt | merge_top_left_fill | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': 'B7:D7', 'top_left_value': None, 'top_left_bg_color': None} | +| merged_cells | pandas | merge_horizontal | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None} | +| merged_cells | pandas | merge_vertical | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None} | +| merged_cells | pandas | merge_value_off_top_left | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None} | +| merged_cells | pandas | merge_top_left_fill | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None} | +| merged_cells | pandas | merge_horizontal | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None} | +| merged_cells | pandas | merge_vertical | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None} | +| merged_cells | pandas | merge_value_off_top_left | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None} | +| merged_cells | pandas | merge_top_left_fill | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None} | +| merged_cells | openpyxl-readonly | merge_horizontal | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None} | +| merged_cells | openpyxl-readonly | merge_vertical | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None} | +| merged_cells | openpyxl-readonly | merge_value_off_top_left | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None} | +| merged_cells | openpyxl-readonly | merge_top_left_fill | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None} | +| merged_cells | polars | merge_horizontal | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None} | +| merged_cells | polars | merge_vertical | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None} | +| merged_cells | polars | merge_value_off_top_left | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None} | +| merged_cells | polars | merge_top_left_fill | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None} | +| merged_cells | tablib | merge_horizontal | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None} | +| merged_cells | tablib | merge_vertical | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None} | +| merged_cells | tablib | merge_value_off_top_left | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None} | +| merged_cells | tablib | merge_top_left_fill | read | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None} | +| merged_cells | tablib | merge_horizontal | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None} | +| merged_cells | tablib | merge_vertical | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None} | +| merged_cells | tablib | merge_value_off_top_left | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None} | +| merged_cells | tablib | merge_top_left_fill | write | data_mismatch | error | Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None} | +| conditional_formatting | python-calamine | cf_cell_gt | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | python-calamine | cf_formula_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={} | +| conditional_formatting | python-calamine | cf_text_contains | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH("foo",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | python-calamine | cf_data_bar | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={} | +| conditional_formatting | python-calamine | cf_color_scale | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={} | +| conditional_formatting | python-calamine | cf_stop_if_true | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={} | +| conditional_formatting | wolfxl | cf_cell_gt | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'format': {}}} | +| conditional_formatting | wolfxl | cf_formula_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'format': {}}} | +| conditional_formatting | wolfxl | cf_text_contains | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH("foo",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH("foo",B2))', 'format': {}}} | +| conditional_formatting | wolfxl | cf_stop_if_true | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'stop_if_true': True, 'format': {}}} | +| conditional_formatting | pylightxl | cf_cell_gt | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| conditional_formatting | pylightxl | cf_formula_cross_sheet | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| conditional_formatting | pylightxl | cf_text_contains | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| conditional_formatting | pylightxl | cf_data_bar | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| conditional_formatting | pylightxl | cf_color_scale | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| conditional_formatting | pylightxl | cf_stop_if_true | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| conditional_formatting | pylightxl | cf_cell_gt | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature | +| conditional_formatting | pylightxl | cf_formula_cross_sheet | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature | +| conditional_formatting | pylightxl | cf_text_contains | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature | +| conditional_formatting | pylightxl | cf_data_bar | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature | +| conditional_formatting | pylightxl | cf_color_scale | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature | +| conditional_formatting | pylightxl | cf_stop_if_true | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature | +| conditional_formatting | pyexcel | cf_cell_gt | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | pyexcel | cf_formula_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={} | +| conditional_formatting | pyexcel | cf_text_contains | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH("foo",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | pyexcel | cf_data_bar | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={} | +| conditional_formatting | pyexcel | cf_color_scale | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={} | +| conditional_formatting | pyexcel | cf_stop_if_true | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={} | +| conditional_formatting | pyexcel | cf_cell_gt | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature | +| conditional_formatting | pyexcel | cf_formula_cross_sheet | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature | +| conditional_formatting | pyexcel | cf_text_contains | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature | +| conditional_formatting | pyexcel | cf_data_bar | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature | +| conditional_formatting | pyexcel | cf_color_scale | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature | +| conditional_formatting | pyexcel | cf_stop_if_true | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature | +| conditional_formatting | xlwt | cf_cell_gt | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting | +| conditional_formatting | xlwt | cf_formula_cross_sheet | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting | +| conditional_formatting | xlwt | cf_text_contains | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting | +| conditional_formatting | xlwt | cf_data_bar | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting | +| conditional_formatting | xlwt | cf_color_scale | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting | +| conditional_formatting | xlwt | cf_stop_if_true | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting | +| conditional_formatting | pandas | cf_cell_gt | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | pandas | cf_formula_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={} | +| conditional_formatting | pandas | cf_text_contains | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH("foo",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | pandas | cf_data_bar | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={} | +| conditional_formatting | pandas | cf_color_scale | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={} | +| conditional_formatting | pandas | cf_stop_if_true | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={} | +| conditional_formatting | pandas | cf_cell_gt | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | pandas | cf_formula_cross_sheet | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={} | +| conditional_formatting | pandas | cf_text_contains | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH("foo",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | pandas | cf_data_bar | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={} | +| conditional_formatting | pandas | cf_color_scale | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={} | +| conditional_formatting | pandas | cf_stop_if_true | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={} | +| conditional_formatting | openpyxl-readonly | cf_cell_gt | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | openpyxl-readonly | cf_formula_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={} | +| conditional_formatting | openpyxl-readonly | cf_text_contains | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH("foo",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | openpyxl-readonly | cf_data_bar | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={} | +| conditional_formatting | openpyxl-readonly | cf_color_scale | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={} | +| conditional_formatting | openpyxl-readonly | cf_stop_if_true | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={} | +| conditional_formatting | polars | cf_cell_gt | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | polars | cf_formula_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={} | +| conditional_formatting | polars | cf_text_contains | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH("foo",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | polars | cf_data_bar | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={} | +| conditional_formatting | polars | cf_color_scale | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={} | +| conditional_formatting | polars | cf_stop_if_true | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={} | +| conditional_formatting | tablib | cf_cell_gt | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | tablib | cf_formula_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={} | +| conditional_formatting | tablib | cf_text_contains | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH("foo",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | tablib | cf_data_bar | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={} | +| conditional_formatting | tablib | cf_color_scale | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={} | +| conditional_formatting | tablib | cf_stop_if_true | read | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={} | +| conditional_formatting | tablib | cf_cell_gt | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | tablib | cf_formula_cross_sheet | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={} | +| conditional_formatting | tablib | cf_text_contains | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH("foo",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={} | +| conditional_formatting | tablib | cf_data_bar | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={} | +| conditional_formatting | tablib | cf_color_scale | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={} | +| conditional_formatting | tablib | cf_stop_if_true | write | data_mismatch | error | Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={} | +| data_validation | python-calamine | dv_list_csv | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '"Red,Green,Blue"', 'allow_blank': True}}, actual={} | +| data_validation | python-calamine | dv_list_range | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={} | +| data_validation | python-calamine | dv_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={} | +| data_validation | python-calamine | dv_custom_formula | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={} | +| data_validation | python-calamine | dv_whole_between | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={} | +| data_validation | pylightxl | dv_list_csv | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| data_validation | pylightxl | dv_list_range | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| data_validation | pylightxl | dv_cross_sheet | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| data_validation | pylightxl | dv_custom_formula | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| data_validation | pylightxl | dv_whole_between | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| data_validation | pylightxl | dv_list_csv | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_data_validation: pylightxl does not implement this feature | +| data_validation | pylightxl | dv_list_range | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_data_validation: pylightxl does not implement this feature | +| data_validation | pylightxl | dv_cross_sheet | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_data_validation: pylightxl does not implement this feature | +| data_validation | pylightxl | dv_custom_formula | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_data_validation: pylightxl does not implement this feature | +| data_validation | pylightxl | dv_whole_between | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_data_validation: pylightxl does not implement this feature | +| data_validation | pyexcel | dv_list_csv | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '"Red,Green,Blue"', 'allow_blank': True}}, actual={} | +| data_validation | pyexcel | dv_list_range | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={} | +| data_validation | pyexcel | dv_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={} | +| data_validation | pyexcel | dv_custom_formula | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={} | +| data_validation | pyexcel | dv_whole_between | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={} | +| data_validation | pyexcel | dv_list_csv | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature | +| data_validation | pyexcel | dv_list_range | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature | +| data_validation | pyexcel | dv_cross_sheet | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature | +| data_validation | pyexcel | dv_custom_formula | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature | +| data_validation | pyexcel | dv_whole_between | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature | +| data_validation | xlwt | dv_list_csv | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_data_validation: xlwt cannot author data validations | +| data_validation | xlwt | dv_list_range | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_data_validation: xlwt cannot author data validations | +| data_validation | xlwt | dv_cross_sheet | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_data_validation: xlwt cannot author data validations | +| data_validation | xlwt | dv_custom_formula | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_data_validation: xlwt cannot author data validations | +| data_validation | xlwt | dv_whole_between | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_data_validation: xlwt cannot author data validations | +| data_validation | pandas | dv_list_csv | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '"Red,Green,Blue"', 'allow_blank': True}}, actual={} | +| data_validation | pandas | dv_list_range | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={} | +| data_validation | pandas | dv_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={} | +| data_validation | pandas | dv_custom_formula | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={} | +| data_validation | pandas | dv_whole_between | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={} | +| data_validation | pandas | dv_list_csv | write | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '"Red,Green,Blue"', 'allow_blank': True}}, actual={} | +| data_validation | pandas | dv_list_range | write | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={} | +| data_validation | pandas | dv_cross_sheet | write | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={} | +| data_validation | pandas | dv_custom_formula | write | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={} | +| data_validation | pandas | dv_whole_between | write | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={} | +| data_validation | openpyxl-readonly | dv_list_csv | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '"Red,Green,Blue"', 'allow_blank': True}}, actual={} | +| data_validation | openpyxl-readonly | dv_list_range | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={} | +| data_validation | openpyxl-readonly | dv_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={} | +| data_validation | openpyxl-readonly | dv_custom_formula | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={} | +| data_validation | openpyxl-readonly | dv_whole_between | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={} | +| data_validation | polars | dv_list_csv | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '"Red,Green,Blue"', 'allow_blank': True}}, actual={} | +| data_validation | polars | dv_list_range | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={} | +| data_validation | polars | dv_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={} | +| data_validation | polars | dv_custom_formula | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={} | +| data_validation | polars | dv_whole_between | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={} | +| data_validation | tablib | dv_list_csv | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '"Red,Green,Blue"', 'allow_blank': True}}, actual={} | +| data_validation | tablib | dv_list_range | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={} | +| data_validation | tablib | dv_cross_sheet | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={} | +| data_validation | tablib | dv_custom_formula | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={} | +| data_validation | tablib | dv_whole_between | read | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={} | +| data_validation | tablib | dv_list_csv | write | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '"Red,Green,Blue"', 'allow_blank': True}}, actual={} | +| data_validation | tablib | dv_list_range | write | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={} | +| data_validation | tablib | dv_cross_sheet | write | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={} | +| data_validation | tablib | dv_custom_formula | write | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={} | +| data_validation | tablib | dv_whole_between | write | data_mismatch | error | Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={} | +| hyperlinks | python-calamine | link_external | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={} | +| hyperlinks | python-calamine | link_internal | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={} | +| hyperlinks | python-calamine | link_mailto | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={} | +| hyperlinks | python-calamine | link_long | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={} | +| hyperlinks | aspose-cells-foss | link_external | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': None, 'tooltip': 'Go to docs', 'internal': False}} | +| hyperlinks | aspose-cells-foss | link_internal | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': None, 'tooltip': 'Jump to target', 'internal': True}} | +| hyperlinks | aspose-cells-foss | link_mailto | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': None, 'tooltip': 'Send email', 'internal': False}} | +| hyperlinks | aspose-cells-foss | link_long | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': None, 'tooltip': 'Encoded URL', 'internal': False}} | +| hyperlinks | pylightxl | link_external | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| hyperlinks | pylightxl | link_internal | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| hyperlinks | pylightxl | link_mailto | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| hyperlinks | pylightxl | link_long | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| hyperlinks | pylightxl | link_external | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_hyperlink: pylightxl does not implement this feature | +| hyperlinks | pylightxl | link_internal | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_hyperlink: pylightxl does not implement this feature | +| hyperlinks | pylightxl | link_mailto | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_hyperlink: pylightxl does not implement this feature | +| hyperlinks | pylightxl | link_long | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_hyperlink: pylightxl does not implement this feature | +| hyperlinks | pyexcel | link_external | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={} | +| hyperlinks | pyexcel | link_internal | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={} | +| hyperlinks | pyexcel | link_mailto | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={} | +| hyperlinks | pyexcel | link_long | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={} | +| hyperlinks | pyexcel | link_external | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature | +| hyperlinks | pyexcel | link_internal | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature | +| hyperlinks | pyexcel | link_mailto | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature | +| hyperlinks | pyexcel | link_long | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature | +| hyperlinks | xlwt | link_external | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter | +| hyperlinks | xlwt | link_internal | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter | +| hyperlinks | xlwt | link_mailto | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter | +| hyperlinks | xlwt | link_long | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter | +| hyperlinks | pandas | link_external | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={} | +| hyperlinks | pandas | link_internal | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={} | +| hyperlinks | pandas | link_mailto | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={} | +| hyperlinks | pandas | link_long | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={} | +| hyperlinks | pandas | link_external | write | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={} | +| hyperlinks | pandas | link_internal | write | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={} | +| hyperlinks | pandas | link_mailto | write | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={} | +| hyperlinks | pandas | link_long | write | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={} | +| hyperlinks | openpyxl-readonly | link_external | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={} | +| hyperlinks | openpyxl-readonly | link_internal | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={} | +| hyperlinks | openpyxl-readonly | link_mailto | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={} | +| hyperlinks | openpyxl-readonly | link_long | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={} | +| hyperlinks | polars | link_external | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={} | +| hyperlinks | polars | link_internal | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={} | +| hyperlinks | polars | link_mailto | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={} | +| hyperlinks | polars | link_long | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={} | +| hyperlinks | tablib | link_external | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={} | +| hyperlinks | tablib | link_internal | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={} | +| hyperlinks | tablib | link_mailto | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={} | +| hyperlinks | tablib | link_long | read | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={} | +| hyperlinks | tablib | link_external | write | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={} | +| hyperlinks | tablib | link_internal | write | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={} | +| hyperlinks | tablib | link_mailto | write | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={} | +| hyperlinks | tablib | link_long | write | data_mismatch | error | Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={} | +| images | python-calamine | image_one_cell | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={} | +| images | python-calamine | image_two_cell_offset | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={} | +| images | aspose-cells-foss | image_one_cell | read | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support read_images: aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind. | +| images | aspose-cells-foss | image_two_cell_offset | read | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support read_images: aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind. | +| images | aspose-cells-foss | image_one_cell | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support add_image: aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors. | +| images | aspose-cells-foss | image_two_cell_offset | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support add_image: aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors. | +| images | pylightxl | image_one_cell | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| images | pylightxl | image_two_cell_offset | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| images | pylightxl | image_one_cell | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_image: pylightxl does not implement this feature | +| images | pylightxl | image_two_cell_offset | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_image: pylightxl does not implement this feature | +| images | pyexcel | image_one_cell | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={} | +| images | pyexcel | image_two_cell_offset | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={} | +| images | pyexcel | image_one_cell | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_image: pyexcel does not expose this worksheet feature | +| images | pyexcel | image_two_cell_offset | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_image: pyexcel does not expose this worksheet feature | +| images | xlwt | image_one_cell | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_image: xlwt cannot embed images in this adapter | +| images | xlwt | image_two_cell_offset | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_image: xlwt cannot embed images in this adapter | +| images | pandas | image_one_cell | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={} | +| images | pandas | image_two_cell_offset | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={} | +| images | pandas | image_one_cell | write | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={} | +| images | pandas | image_two_cell_offset | write | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={} | +| images | xlsxwriter-constmem | image_one_cell | write | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={} | +| images | xlsxwriter-constmem | image_two_cell_offset | write | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={} | +| images | openpyxl-readonly | image_one_cell | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={} | +| images | openpyxl-readonly | image_two_cell_offset | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={} | +| images | polars | image_one_cell | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={} | +| images | polars | image_two_cell_offset | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={} | +| images | tablib | image_one_cell | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={} | +| images | tablib | image_two_cell_offset | read | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={} | +| images | tablib | image_one_cell | write | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={} | +| images | tablib | image_two_cell_offset | write | data_mismatch | error | Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={} | +| comments | python-calamine | comment_legacy | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={} | +| comments | python-calamine | comment_threaded | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={} | +| comments | python-calamine | comment_author | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={} | +| comments | aspose-cells-foss | comment_legacy | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={'comment': {'cell': 'B2', 'text': 'None:Legacy note', 'threaded': False}} | +| comments | aspose-cells-foss | comment_threaded | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={'comment': {'cell': 'B3', 'text': 'None:Threaded fallback', 'threaded': False}} | +| comments | aspose-cells-foss | comment_author | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={'comment': {'cell': 'B4', 'text': 'None:Another note', 'threaded': False}} | +| comments | pylightxl | comment_legacy | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={} | +| comments | pylightxl | comment_threaded | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={} | +| comments | pylightxl | comment_author | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={} | +| comments | pylightxl | comment_legacy | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_comment: pylightxl does not implement this feature | +| comments | pylightxl | comment_threaded | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_comment: pylightxl does not implement this feature | +| comments | pylightxl | comment_author | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support add_comment: pylightxl does not implement this feature | +| comments | pyexcel | comment_legacy | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={} | +| comments | pyexcel | comment_threaded | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={} | +| comments | pyexcel | comment_author | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={} | +| comments | pyexcel | comment_legacy | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_comment: pyexcel does not expose this worksheet feature | +| comments | pyexcel | comment_threaded | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_comment: pyexcel does not expose this worksheet feature | +| comments | pyexcel | comment_author | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support add_comment: pyexcel does not expose this worksheet feature | +| comments | xlwt | comment_legacy | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_comment: xlwt cannot author comments | +| comments | xlwt | comment_threaded | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_comment: xlwt cannot author comments | +| comments | xlwt | comment_author | write | unsupported_feature | warning | UnsupportedAdapterOperationError: xlwt does not support add_comment: xlwt cannot author comments | +| comments | pandas | comment_legacy | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={} | +| comments | pandas | comment_threaded | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={} | +| comments | pandas | comment_author | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={} | +| comments | pandas | comment_legacy | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={} | +| comments | pandas | comment_threaded | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={} | +| comments | pandas | comment_author | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={} | +| comments | xlsxwriter-constmem | comment_legacy | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={} | +| comments | xlsxwriter-constmem | comment_threaded | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={} | +| comments | xlsxwriter-constmem | comment_author | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={} | +| comments | openpyxl-readonly | comment_legacy | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={} | +| comments | openpyxl-readonly | comment_threaded | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={} | +| comments | openpyxl-readonly | comment_author | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={} | +| comments | polars | comment_legacy | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={} | +| comments | polars | comment_threaded | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={} | +| comments | polars | comment_author | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={} | +| comments | tablib | comment_legacy | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={} | +| comments | tablib | comment_threaded | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={} | +| comments | tablib | comment_author | read | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={} | +| comments | tablib | comment_legacy | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={} | +| comments | tablib | comment_threaded | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={} | +| comments | tablib | comment_author | write | data_mismatch | error | Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={} | +| freeze_panes | python-calamine | freeze_b2 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | python-calamine | freeze_d5 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | python-calamine | split_2x1 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}} | +| freeze_panes | pylightxl | freeze_b2 | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| freeze_panes | pylightxl | freeze_d5 | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| freeze_panes | pylightxl | split_2x1 | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| freeze_panes | pylightxl | freeze_b2 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support set_freeze_panes: pylightxl does not implement this feature | +| freeze_panes | pylightxl | freeze_d5 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support set_freeze_panes: pylightxl does not implement this feature | +| freeze_panes | pylightxl | split_2x1 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pylightxl does not support set_freeze_panes: pylightxl does not implement this feature | +| freeze_panes | pyexcel | freeze_b2 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | pyexcel | freeze_d5 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | pyexcel | split_2x1 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}} | +| freeze_panes | pyexcel | freeze_b2 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support set_freeze_panes: pyexcel does not expose this worksheet feature | +| freeze_panes | pyexcel | freeze_d5 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support set_freeze_panes: pyexcel does not expose this worksheet feature | +| freeze_panes | pyexcel | split_2x1 | write | unsupported_feature | warning | UnsupportedAdapterOperationError: pyexcel does not support set_freeze_panes: pyexcel does not expose this worksheet feature | +| freeze_panes | xlwt | freeze_b2 | write | internal | error | AttributeError: 'Sheet' object has no attribute 'frozen_row_count' | +| freeze_panes | xlwt | freeze_d5 | write | internal | error | AttributeError: 'Sheet' object has no attribute 'frozen_row_count' | +| freeze_panes | xlwt | split_2x1 | write | internal | error | AttributeError: 'Sheet' object has no attribute 'frozen_row_count' | +| freeze_panes | pandas | freeze_b2 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | pandas | freeze_d5 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | pandas | split_2x1 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}} | +| freeze_panes | pandas | freeze_b2 | write | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | pandas | freeze_d5 | write | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | pandas | split_2x1 | write | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}} | +| freeze_panes | openpyxl-readonly | freeze_b2 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | openpyxl-readonly | freeze_d5 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | openpyxl-readonly | split_2x1 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}} | +| freeze_panes | polars | freeze_b2 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | polars | freeze_d5 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | polars | split_2x1 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}} | +| freeze_panes | tablib | freeze_b2 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | tablib | freeze_d5 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | tablib | split_2x1 | read | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}} | +| freeze_panes | tablib | freeze_b2 | write | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | tablib | freeze_d5 | write | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}} | +| freeze_panes | tablib | split_2x1 | write | data_mismatch | error | Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}} | +| named_ranges | xlsxwriter | nr_simple_cell | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement named range writes | +| named_ranges | xlsxwriter | nr_cell_range | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement named range writes | +| named_ranges | xlsxwriter | nr_formula_ref | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement named range writes | +| named_ranges | xlsxwriter | nr_sheet_scope | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement named range writes | +| named_ranges | xlsxwriter | nr_cross_sheet | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement named range writes | +| named_ranges | xlsxwriter | nr_special_chars | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement named range writes | +| named_ranges | python-calamine | nr_simple_cell | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement named range reads | +| named_ranges | python-calamine | nr_cell_range | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement named range reads | +| named_ranges | python-calamine | nr_formula_ref | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement named range reads | +| named_ranges | python-calamine | nr_sheet_scope | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement named range reads | +| named_ranges | python-calamine | nr_cross_sheet | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement named range reads | +| named_ranges | python-calamine | nr_special_chars | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement named range reads | +| named_ranges | aspose-cells-foss | nr_sheet_scope | read | data_mismatch | error | Expected values did not match actual values: expected={'name': 'LocalName', 'scope': 'sheet', 'refers_to': 'named_ranges!$B$5', 'value': 'local'}, actual={'name': 'LocalName', 'scope': 'sheet', 'refers_to': 'named_ranges!$B$5', 'value': None} | +| named_ranges | wolfxl | nr_sheet_scope | write | data_mismatch | error | Expected values did not match actual values: expected={'name': 'LocalName', 'scope': 'sheet', 'refers_to': 'named_ranges!$B$5', 'value': 'local'}, actual={'name': 'LocalName', 'scope': 'not_found', 'refers_to': ''} | +| named_ranges | pylightxl | nr_simple_cell | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| named_ranges | pylightxl | nr_cell_range | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| named_ranges | pylightxl | nr_formula_ref | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| named_ranges | pylightxl | nr_sheet_scope | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| named_ranges | pylightxl | nr_cross_sheet | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| named_ranges | pylightxl | nr_special_chars | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| named_ranges | pylightxl | nr_simple_cell | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement named range writes | +| named_ranges | pylightxl | nr_cell_range | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement named range writes | +| named_ranges | pylightxl | nr_formula_ref | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement named range writes | +| named_ranges | pylightxl | nr_sheet_scope | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement named range writes | +| named_ranges | pylightxl | nr_cross_sheet | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement named range writes | +| named_ranges | pylightxl | nr_special_chars | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement named range writes | +| named_ranges | pyexcel | nr_simple_cell | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range reads | +| named_ranges | pyexcel | nr_cell_range | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range reads | +| named_ranges | pyexcel | nr_formula_ref | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range reads | +| named_ranges | pyexcel | nr_sheet_scope | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range reads | +| named_ranges | pyexcel | nr_cross_sheet | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range reads | +| named_ranges | pyexcel | nr_special_chars | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range reads | +| named_ranges | pyexcel | nr_simple_cell | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range writes | +| named_ranges | pyexcel | nr_cell_range | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range writes | +| named_ranges | pyexcel | nr_formula_ref | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range writes | +| named_ranges | pyexcel | nr_sheet_scope | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range writes | +| named_ranges | pyexcel | nr_cross_sheet | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range writes | +| named_ranges | pyexcel | nr_special_chars | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement named range writes | +| named_ranges | xlwt | nr_simple_cell | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement named range writes | +| named_ranges | xlwt | nr_cell_range | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement named range writes | +| named_ranges | xlwt | nr_formula_ref | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement named range writes | +| named_ranges | xlwt | nr_sheet_scope | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement named range writes | +| named_ranges | xlwt | nr_cross_sheet | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement named range writes | +| named_ranges | xlwt | nr_special_chars | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement named range writes | +| named_ranges | pandas | nr_simple_cell | read | unsupported_feature | warning | NotImplementedError: pandas does not implement named range reads | +| named_ranges | pandas | nr_cell_range | read | unsupported_feature | warning | NotImplementedError: pandas does not implement named range reads | +| named_ranges | pandas | nr_formula_ref | read | unsupported_feature | warning | NotImplementedError: pandas does not implement named range reads | +| named_ranges | pandas | nr_sheet_scope | read | unsupported_feature | warning | NotImplementedError: pandas does not implement named range reads | +| named_ranges | pandas | nr_cross_sheet | read | unsupported_feature | warning | NotImplementedError: pandas does not implement named range reads | +| named_ranges | pandas | nr_special_chars | read | unsupported_feature | warning | NotImplementedError: pandas does not implement named range reads | +| named_ranges | pandas | nr_simple_cell | write | unsupported_feature | warning | NotImplementedError: pandas does not implement named range writes | +| named_ranges | pandas | nr_cell_range | write | unsupported_feature | warning | NotImplementedError: pandas does not implement named range writes | +| named_ranges | pandas | nr_formula_ref | write | unsupported_feature | warning | NotImplementedError: pandas does not implement named range writes | +| named_ranges | pandas | nr_sheet_scope | write | unsupported_feature | warning | NotImplementedError: pandas does not implement named range writes | +| named_ranges | pandas | nr_cross_sheet | write | unsupported_feature | warning | NotImplementedError: pandas does not implement named range writes | +| named_ranges | pandas | nr_special_chars | write | unsupported_feature | warning | NotImplementedError: pandas does not implement named range writes | +| named_ranges | xlsxwriter-constmem | nr_simple_cell | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement named range writes | +| named_ranges | xlsxwriter-constmem | nr_cell_range | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement named range writes | +| named_ranges | xlsxwriter-constmem | nr_formula_ref | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement named range writes | +| named_ranges | xlsxwriter-constmem | nr_sheet_scope | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement named range writes | +| named_ranges | xlsxwriter-constmem | nr_cross_sheet | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement named range writes | +| named_ranges | xlsxwriter-constmem | nr_special_chars | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement named range writes | +| named_ranges | openpyxl-readonly | nr_simple_cell | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement named range reads | +| named_ranges | openpyxl-readonly | nr_cell_range | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement named range reads | +| named_ranges | openpyxl-readonly | nr_formula_ref | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement named range reads | +| named_ranges | openpyxl-readonly | nr_sheet_scope | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement named range reads | +| named_ranges | openpyxl-readonly | nr_cross_sheet | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement named range reads | +| named_ranges | openpyxl-readonly | nr_special_chars | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement named range reads | +| named_ranges | polars | nr_simple_cell | read | unsupported_feature | warning | NotImplementedError: polars does not implement named range reads | +| named_ranges | polars | nr_cell_range | read | unsupported_feature | warning | NotImplementedError: polars does not implement named range reads | +| named_ranges | polars | nr_formula_ref | read | unsupported_feature | warning | NotImplementedError: polars does not implement named range reads | +| named_ranges | polars | nr_sheet_scope | read | unsupported_feature | warning | NotImplementedError: polars does not implement named range reads | +| named_ranges | polars | nr_cross_sheet | read | unsupported_feature | warning | NotImplementedError: polars does not implement named range reads | +| named_ranges | polars | nr_special_chars | read | unsupported_feature | warning | NotImplementedError: polars does not implement named range reads | +| named_ranges | tablib | nr_simple_cell | read | unsupported_feature | warning | NotImplementedError: tablib does not implement named range reads | +| named_ranges | tablib | nr_cell_range | read | unsupported_feature | warning | NotImplementedError: tablib does not implement named range reads | +| named_ranges | tablib | nr_formula_ref | read | unsupported_feature | warning | NotImplementedError: tablib does not implement named range reads | +| named_ranges | tablib | nr_sheet_scope | read | unsupported_feature | warning | NotImplementedError: tablib does not implement named range reads | +| named_ranges | tablib | nr_cross_sheet | read | unsupported_feature | warning | NotImplementedError: tablib does not implement named range reads | +| named_ranges | tablib | nr_special_chars | read | unsupported_feature | warning | NotImplementedError: tablib does not implement named range reads | +| named_ranges | tablib | nr_simple_cell | write | unsupported_feature | warning | NotImplementedError: tablib does not implement named range writes | +| named_ranges | tablib | nr_cell_range | write | unsupported_feature | warning | NotImplementedError: tablib does not implement named range writes | +| named_ranges | tablib | nr_formula_ref | write | unsupported_feature | warning | NotImplementedError: tablib does not implement named range writes | +| named_ranges | tablib | nr_sheet_scope | write | unsupported_feature | warning | NotImplementedError: tablib does not implement named range writes | +| named_ranges | tablib | nr_cross_sheet | write | unsupported_feature | warning | NotImplementedError: tablib does not implement named range writes | +| named_ranges | tablib | nr_special_chars | write | unsupported_feature | warning | NotImplementedError: tablib does not implement named range writes | +| tables | xlsxwriter | tbl_basic | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement table writes | +| tables | xlsxwriter | tbl_with_totals | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement table writes | +| tables | xlsxwriter | tbl_no_style | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement table writes | +| tables | xlsxwriter | tbl_single_col | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement table writes | +| tables | xlsxwriter | tbl_single_row | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement table writes | +| tables | xlsxwriter | tbl_autofilter | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement table writes | +| tables | python-calamine | tbl_basic | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement table reads | +| tables | python-calamine | tbl_with_totals | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement table reads | +| tables | python-calamine | tbl_no_style | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement table reads | +| tables | python-calamine | tbl_single_col | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement table reads | +| tables | python-calamine | tbl_single_row | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement table reads | +| tables | python-calamine | tbl_autofilter | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement table reads | +| tables | aspose-cells-foss | tbl_with_totals | read | data_mismatch | error | Expected values did not match actual values: expected={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': True, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 1}}, actual={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': False, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 0}} | +| tables | aspose-cells-foss | tbl_no_style | read | data_mismatch | error | Expected values did not match actual values: expected={'table': {'name': 'PlainTable', 'ref': 'E13:F16', 'header_row': True, 'totals_row': False, 'style': None, 'columns': ['Key', 'Value']}}, actual={'table': {'name': 'PlainTable', 'ref': 'E13:F16', 'header_row': True, 'totals_row': False, 'style': 'TableStyleMedium2', 'columns': ['Key', 'Value']}} | +| tables | aspose-cells-foss | tbl_with_totals | write | data_mismatch | error | Expected values did not match actual values: expected={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': True, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 1}}, actual={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': False, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 0}} | +| tables | aspose-cells-foss | tbl_no_style | write | data_mismatch | error | Expected values did not match actual values: expected={'table': {'name': 'PlainTable', 'ref': 'E13:F16', 'header_row': True, 'totals_row': False, 'style': None, 'columns': ['Key', 'Value']}}, actual={'table': {'name': 'PlainTable', 'ref': 'E13:F16', 'header_row': True, 'totals_row': False, 'style': 'TableStyleMedium2', 'columns': ['Key', 'Value']}} | +| tables | pylightxl | tbl_basic | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| tables | pylightxl | tbl_with_totals | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| tables | pylightxl | tbl_no_style | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| tables | pylightxl | tbl_single_col | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| tables | pylightxl | tbl_single_row | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| tables | pylightxl | tbl_autofilter | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| tables | pylightxl | tbl_basic | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement table writes | +| tables | pylightxl | tbl_with_totals | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement table writes | +| tables | pylightxl | tbl_no_style | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement table writes | +| tables | pylightxl | tbl_single_col | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement table writes | +| tables | pylightxl | tbl_single_row | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement table writes | +| tables | pylightxl | tbl_autofilter | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement table writes | +| tables | pyexcel | tbl_basic | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table reads | +| tables | pyexcel | tbl_with_totals | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table reads | +| tables | pyexcel | tbl_no_style | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table reads | +| tables | pyexcel | tbl_single_col | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table reads | +| tables | pyexcel | tbl_single_row | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table reads | +| tables | pyexcel | tbl_autofilter | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table reads | +| tables | pyexcel | tbl_basic | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table writes | +| tables | pyexcel | tbl_with_totals | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table writes | +| tables | pyexcel | tbl_no_style | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table writes | +| tables | pyexcel | tbl_single_col | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table writes | +| tables | pyexcel | tbl_single_row | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table writes | +| tables | pyexcel | tbl_autofilter | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement table writes | +| tables | xlwt | tbl_basic | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement table writes | +| tables | xlwt | tbl_with_totals | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement table writes | +| tables | xlwt | tbl_no_style | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement table writes | +| tables | xlwt | tbl_single_col | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement table writes | +| tables | xlwt | tbl_single_row | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement table writes | +| tables | xlwt | tbl_autofilter | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement table writes | +| tables | pandas | tbl_basic | read | unsupported_feature | warning | NotImplementedError: pandas does not implement table reads | +| tables | pandas | tbl_with_totals | read | unsupported_feature | warning | NotImplementedError: pandas does not implement table reads | +| tables | pandas | tbl_no_style | read | unsupported_feature | warning | NotImplementedError: pandas does not implement table reads | +| tables | pandas | tbl_single_col | read | unsupported_feature | warning | NotImplementedError: pandas does not implement table reads | +| tables | pandas | tbl_single_row | read | unsupported_feature | warning | NotImplementedError: pandas does not implement table reads | +| tables | pandas | tbl_autofilter | read | unsupported_feature | warning | NotImplementedError: pandas does not implement table reads | +| tables | pandas | tbl_basic | write | unsupported_feature | warning | NotImplementedError: pandas does not implement table writes | +| tables | pandas | tbl_with_totals | write | unsupported_feature | warning | NotImplementedError: pandas does not implement table writes | +| tables | pandas | tbl_no_style | write | unsupported_feature | warning | NotImplementedError: pandas does not implement table writes | +| tables | pandas | tbl_single_col | write | unsupported_feature | warning | NotImplementedError: pandas does not implement table writes | +| tables | pandas | tbl_single_row | write | unsupported_feature | warning | NotImplementedError: pandas does not implement table writes | +| tables | pandas | tbl_autofilter | write | unsupported_feature | warning | NotImplementedError: pandas does not implement table writes | +| tables | xlsxwriter-constmem | tbl_basic | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement table writes | +| tables | xlsxwriter-constmem | tbl_with_totals | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement table writes | +| tables | xlsxwriter-constmem | tbl_no_style | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement table writes | +| tables | xlsxwriter-constmem | tbl_single_col | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement table writes | +| tables | xlsxwriter-constmem | tbl_single_row | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement table writes | +| tables | xlsxwriter-constmem | tbl_autofilter | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement table writes | +| tables | openpyxl-readonly | tbl_basic | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement table reads | +| tables | openpyxl-readonly | tbl_with_totals | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement table reads | +| tables | openpyxl-readonly | tbl_no_style | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement table reads | +| tables | openpyxl-readonly | tbl_single_col | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement table reads | +| tables | openpyxl-readonly | tbl_single_row | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement table reads | +| tables | openpyxl-readonly | tbl_autofilter | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement table reads | +| tables | polars | tbl_basic | read | unsupported_feature | warning | NotImplementedError: polars does not implement table reads | +| tables | polars | tbl_with_totals | read | unsupported_feature | warning | NotImplementedError: polars does not implement table reads | +| tables | polars | tbl_no_style | read | unsupported_feature | warning | NotImplementedError: polars does not implement table reads | +| tables | polars | tbl_single_col | read | unsupported_feature | warning | NotImplementedError: polars does not implement table reads | +| tables | polars | tbl_single_row | read | unsupported_feature | warning | NotImplementedError: polars does not implement table reads | +| tables | polars | tbl_autofilter | read | unsupported_feature | warning | NotImplementedError: polars does not implement table reads | +| tables | tablib | tbl_basic | read | unsupported_feature | warning | NotImplementedError: tablib does not implement table reads | +| tables | tablib | tbl_with_totals | read | unsupported_feature | warning | NotImplementedError: tablib does not implement table reads | +| tables | tablib | tbl_no_style | read | unsupported_feature | warning | NotImplementedError: tablib does not implement table reads | +| tables | tablib | tbl_single_col | read | unsupported_feature | warning | NotImplementedError: tablib does not implement table reads | +| tables | tablib | tbl_single_row | read | unsupported_feature | warning | NotImplementedError: tablib does not implement table reads | +| tables | tablib | tbl_autofilter | read | unsupported_feature | warning | NotImplementedError: tablib does not implement table reads | +| tables | tablib | tbl_basic | write | unsupported_feature | warning | NotImplementedError: tablib does not implement table writes | +| tables | tablib | tbl_with_totals | write | unsupported_feature | warning | NotImplementedError: tablib does not implement table writes | +| tables | tablib | tbl_no_style | write | unsupported_feature | warning | NotImplementedError: tablib does not implement table writes | +| tables | tablib | tbl_single_col | write | unsupported_feature | warning | NotImplementedError: tablib does not implement table writes | +| tables | tablib | tbl_single_row | write | unsupported_feature | warning | NotImplementedError: tablib does not implement table writes | +| tables | tablib | tbl_autofilter | write | unsupported_feature | warning | NotImplementedError: tablib does not implement table writes | +| sheet_protection | xlsxwriter | prot_basic | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement sheet protection writes | +| sheet_protection | xlsxwriter | prot_password | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement sheet protection writes | +| sheet_protection | xlsxwriter | prot_granular | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement sheet protection writes | +| sheet_protection | python-calamine | prot_basic | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement sheet protection reads | +| sheet_protection | python-calamine | prot_password | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement sheet protection reads | +| sheet_protection | python-calamine | prot_granular | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement sheet protection reads | +| sheet_protection | pylightxl | prot_basic | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| sheet_protection | pylightxl | prot_password | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| sheet_protection | pylightxl | prot_granular | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| sheet_protection | pylightxl | prot_basic | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement sheet protection writes | +| sheet_protection | pylightxl | prot_password | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement sheet protection writes | +| sheet_protection | pylightxl | prot_granular | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement sheet protection writes | +| sheet_protection | pyexcel | prot_basic | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement sheet protection reads | +| sheet_protection | pyexcel | prot_password | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement sheet protection reads | +| sheet_protection | pyexcel | prot_granular | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement sheet protection reads | +| sheet_protection | pyexcel | prot_basic | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement sheet protection writes | +| sheet_protection | pyexcel | prot_password | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement sheet protection writes | +| sheet_protection | pyexcel | prot_granular | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement sheet protection writes | +| sheet_protection | xlwt | prot_basic | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement sheet protection writes | +| sheet_protection | xlwt | prot_password | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement sheet protection writes | +| sheet_protection | xlwt | prot_granular | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement sheet protection writes | +| sheet_protection | pandas | prot_basic | read | unsupported_feature | warning | NotImplementedError: pandas does not implement sheet protection reads | +| sheet_protection | pandas | prot_password | read | unsupported_feature | warning | NotImplementedError: pandas does not implement sheet protection reads | +| sheet_protection | pandas | prot_granular | read | unsupported_feature | warning | NotImplementedError: pandas does not implement sheet protection reads | +| sheet_protection | pandas | prot_basic | write | unsupported_feature | warning | NotImplementedError: pandas does not implement sheet protection writes | +| sheet_protection | pandas | prot_password | write | unsupported_feature | warning | NotImplementedError: pandas does not implement sheet protection writes | +| sheet_protection | pandas | prot_granular | write | unsupported_feature | warning | NotImplementedError: pandas does not implement sheet protection writes | +| sheet_protection | xlsxwriter-constmem | prot_basic | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement sheet protection writes | +| sheet_protection | xlsxwriter-constmem | prot_password | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement sheet protection writes | +| sheet_protection | xlsxwriter-constmem | prot_granular | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement sheet protection writes | +| sheet_protection | openpyxl-readonly | prot_basic | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement sheet protection reads | +| sheet_protection | openpyxl-readonly | prot_password | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement sheet protection reads | +| sheet_protection | openpyxl-readonly | prot_granular | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement sheet protection reads | +| sheet_protection | polars | prot_basic | read | unsupported_feature | warning | NotImplementedError: polars does not implement sheet protection reads | +| sheet_protection | polars | prot_password | read | unsupported_feature | warning | NotImplementedError: polars does not implement sheet protection reads | +| sheet_protection | polars | prot_granular | read | unsupported_feature | warning | NotImplementedError: polars does not implement sheet protection reads | +| sheet_protection | tablib | prot_basic | read | unsupported_feature | warning | NotImplementedError: tablib does not implement sheet protection reads | +| sheet_protection | tablib | prot_password | read | unsupported_feature | warning | NotImplementedError: tablib does not implement sheet protection reads | +| sheet_protection | tablib | prot_granular | read | unsupported_feature | warning | NotImplementedError: tablib does not implement sheet protection reads | +| sheet_protection | tablib | prot_basic | write | unsupported_feature | warning | NotImplementedError: tablib does not implement sheet protection writes | +| sheet_protection | tablib | prot_password | write | unsupported_feature | warning | NotImplementedError: tablib does not implement sheet protection writes | +| sheet_protection | tablib | prot_granular | write | unsupported_feature | warning | NotImplementedError: tablib does not implement sheet protection writes | +| page_setup | xlsxwriter | page_setup_landscape | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement page setup writes | +| page_setup | xlsxwriter | page_setup_scale | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement page setup writes | +| page_setup | xlsxwriter | page_setup_titles | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement page setup writes | +| page_setup | python-calamine | page_setup_landscape | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement page setup reads | +| page_setup | python-calamine | page_setup_scale | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement page setup reads | +| page_setup | python-calamine | page_setup_titles | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement page setup reads | +| page_setup | aspose-cells-foss | page_setup_landscape | read | data_mismatch | error | Expected values did not match actual values: expected={'page_setup': {'orientation': 'landscape', 'fit_to_width': 1, 'fit_to_height': None, 'scale': None, 'print_title_rows': None, 'header_center': None, 'footer_center': None}}, actual={'page_setup': {'orientation': 'landscape', 'fit_to_width': 1, 'fit_to_height': None, 'scale': 100, 'print_title_rows': None, 'header_center': None, 'footer_center': None}} | +| page_setup | aspose-cells-foss | page_setup_titles | read | data_mismatch | error | Expected values did not match actual values: expected={'page_setup': {'orientation': None, 'fit_to_width': None, 'fit_to_height': None, 'scale': None, 'print_title_rows': '$1:$2', 'header_center': 'ExcelBench Report', 'footer_center': 'Page &P'}}, actual={'page_setup': {'orientation': 'portrait', 'fit_to_width': None, 'fit_to_height': None, 'scale': 100, 'print_title_rows': None, 'header_center': 'ExcelBench Report', 'footer_center': 'Page &P'}} | +| page_setup | aspose-cells-foss | page_setup_landscape | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support set_page_setup: aspose-cells-foss has no print-title-rows API. | +| page_setup | aspose-cells-foss | page_setup_scale | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support set_page_setup: aspose-cells-foss has no print-title-rows API. | +| page_setup | aspose-cells-foss | page_setup_titles | write | unsupported_feature | warning | UnsupportedAdapterOperationError: aspose-cells-foss does not support set_page_setup: aspose-cells-foss has no print-title-rows API. | +| page_setup | wolfxl | page_setup_titles | write | data_mismatch | error | Expected values did not match actual values: expected={'page_setup': {'orientation': None, 'fit_to_width': None, 'fit_to_height': None, 'scale': None, 'print_title_rows': '$1:$2', 'header_center': 'ExcelBench Report', 'footer_center': 'Page &P'}}, actual={'page_setup': {'orientation': None, 'fit_to_width': None, 'fit_to_height': None, 'scale': None, 'print_title_rows': None, 'header_center': 'ExcelBench Report', 'footer_center': 'Page &P'}} | +| page_setup | pylightxl | page_setup_landscape | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| page_setup | pylightxl | page_setup_scale | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| page_setup | pylightxl | page_setup_titles | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| page_setup | pylightxl | page_setup_landscape | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement page setup writes | +| page_setup | pylightxl | page_setup_scale | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement page setup writes | +| page_setup | pylightxl | page_setup_titles | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement page setup writes | +| page_setup | pyexcel | page_setup_landscape | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement page setup reads | +| page_setup | pyexcel | page_setup_scale | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement page setup reads | +| page_setup | pyexcel | page_setup_titles | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement page setup reads | +| page_setup | pyexcel | page_setup_landscape | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement page setup writes | +| page_setup | pyexcel | page_setup_scale | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement page setup writes | +| page_setup | pyexcel | page_setup_titles | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement page setup writes | +| page_setup | xlwt | page_setup_landscape | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement page setup writes | +| page_setup | xlwt | page_setup_scale | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement page setup writes | +| page_setup | xlwt | page_setup_titles | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement page setup writes | +| page_setup | pandas | page_setup_landscape | read | unsupported_feature | warning | NotImplementedError: pandas does not implement page setup reads | +| page_setup | pandas | page_setup_scale | read | unsupported_feature | warning | NotImplementedError: pandas does not implement page setup reads | +| page_setup | pandas | page_setup_titles | read | unsupported_feature | warning | NotImplementedError: pandas does not implement page setup reads | +| page_setup | pandas | page_setup_landscape | write | unsupported_feature | warning | NotImplementedError: pandas does not implement page setup writes | +| page_setup | pandas | page_setup_scale | write | unsupported_feature | warning | NotImplementedError: pandas does not implement page setup writes | +| page_setup | pandas | page_setup_titles | write | unsupported_feature | warning | NotImplementedError: pandas does not implement page setup writes | +| page_setup | xlsxwriter-constmem | page_setup_landscape | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement page setup writes | +| page_setup | xlsxwriter-constmem | page_setup_scale | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement page setup writes | +| page_setup | xlsxwriter-constmem | page_setup_titles | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement page setup writes | +| page_setup | openpyxl-readonly | page_setup_landscape | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement page setup reads | +| page_setup | openpyxl-readonly | page_setup_scale | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement page setup reads | +| page_setup | openpyxl-readonly | page_setup_titles | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement page setup reads | +| page_setup | polars | page_setup_landscape | read | unsupported_feature | warning | NotImplementedError: polars does not implement page setup reads | +| page_setup | polars | page_setup_scale | read | unsupported_feature | warning | NotImplementedError: polars does not implement page setup reads | +| page_setup | polars | page_setup_titles | read | unsupported_feature | warning | NotImplementedError: polars does not implement page setup reads | +| page_setup | tablib | page_setup_landscape | read | unsupported_feature | warning | NotImplementedError: tablib does not implement page setup reads | +| page_setup | tablib | page_setup_scale | read | unsupported_feature | warning | NotImplementedError: tablib does not implement page setup reads | +| page_setup | tablib | page_setup_titles | read | unsupported_feature | warning | NotImplementedError: tablib does not implement page setup reads | +| page_setup | tablib | page_setup_landscape | write | unsupported_feature | warning | NotImplementedError: tablib does not implement page setup writes | +| page_setup | tablib | page_setup_scale | write | unsupported_feature | warning | NotImplementedError: tablib does not implement page setup writes | +| page_setup | tablib | page_setup_titles | write | unsupported_feature | warning | NotImplementedError: tablib does not implement page setup writes | +| chart_anchor | xlsxwriter | chart_bar | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement chart anchor writes | +| chart_anchor | xlsxwriter | chart_line | write | unsupported_feature | warning | NotImplementedError: xlsxwriter does not implement chart anchor writes | +| chart_anchor | python-calamine | chart_bar | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement chart anchor reads | +| chart_anchor | python-calamine | chart_line | read | unsupported_feature | warning | NotImplementedError: python-calamine does not implement chart anchor reads | +| chart_anchor | pylightxl | chart_bar | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| chart_anchor | pylightxl | chart_line | read | invalid_input | error | TypeError: expected string or bytes-like object, got 'NoneType' | +| chart_anchor | pylightxl | chart_bar | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement chart anchor writes | +| chart_anchor | pylightxl | chart_line | write | unsupported_feature | warning | NotImplementedError: pylightxl does not implement chart anchor writes | +| chart_anchor | pyexcel | chart_bar | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement chart anchor reads | +| chart_anchor | pyexcel | chart_line | read | unsupported_feature | warning | NotImplementedError: pyexcel does not implement chart anchor reads | +| chart_anchor | pyexcel | chart_bar | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement chart anchor writes | +| chart_anchor | pyexcel | chart_line | write | unsupported_feature | warning | NotImplementedError: pyexcel does not implement chart anchor writes | +| chart_anchor | xlwt | chart_bar | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement chart anchor writes | +| chart_anchor | xlwt | chart_line | write | unsupported_feature | warning | NotImplementedError: xlwt does not implement chart anchor writes | +| chart_anchor | pandas | chart_bar | read | unsupported_feature | warning | NotImplementedError: pandas does not implement chart anchor reads | +| chart_anchor | pandas | chart_line | read | unsupported_feature | warning | NotImplementedError: pandas does not implement chart anchor reads | +| chart_anchor | pandas | chart_bar | write | unsupported_feature | warning | NotImplementedError: pandas does not implement chart anchor writes | +| chart_anchor | pandas | chart_line | write | unsupported_feature | warning | NotImplementedError: pandas does not implement chart anchor writes | +| chart_anchor | xlsxwriter-constmem | chart_bar | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement chart anchor writes | +| chart_anchor | xlsxwriter-constmem | chart_line | write | unsupported_feature | warning | NotImplementedError: xlsxwriter-constmem does not implement chart anchor writes | +| chart_anchor | openpyxl-readonly | chart_bar | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement chart anchor reads | +| chart_anchor | openpyxl-readonly | chart_line | read | unsupported_feature | warning | NotImplementedError: openpyxl-readonly does not implement chart anchor reads | +| chart_anchor | polars | chart_bar | read | unsupported_feature | warning | NotImplementedError: polars does not implement chart anchor reads | +| chart_anchor | polars | chart_line | read | unsupported_feature | warning | NotImplementedError: polars does not implement chart anchor reads | +| chart_anchor | tablib | chart_bar | read | unsupported_feature | warning | NotImplementedError: tablib does not implement chart anchor reads | +| chart_anchor | tablib | chart_line | read | unsupported_feature | warning | NotImplementedError: tablib does not implement chart anchor reads | +| chart_anchor | tablib | chart_bar | write | unsupported_feature | warning | NotImplementedError: tablib does not implement chart anchor writes | +| chart_anchor | tablib | chart_line | write | unsupported_feature | warning | NotImplementedError: tablib does not implement chart anchor writes | + +## Detailed Results + + +### alignment + +**aspose-cells-foss** — Read: 🟠 1 | Write: 🟠 1 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Align - left | basic | ✅ | ✅ | +| Align - center | basic | ✅ | ✅ | +| Align - right | basic | ✅ | ✅ | +| Align - top | basic | ✅ | ✅ | +| Align - center | basic | ✅ | ✅ | +| Align - bottom | basic | ❌ | ❌ | +| Align - wrap text | basic | ✅ | ✅ | +| Align - rotation 45 | basic | ✅ | ✅ | +| Align - indent 2 | basic | ✅ | ✅ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Align - left | basic | ❌ | +| Align - center | basic | ❌ | +| Align - right | basic | ❌ | +| Align - top | basic | ❌ | +| Align - center | basic | ❌ | +| Align - bottom | basic | ❌ | +| Align - wrap text | basic | ❌ | +| Align - rotation 45 | basic | ❌ | +| Align - indent 2 | basic | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Align - left | basic | ❌ | ❌ | +| Align - center | basic | ❌ | ❌ | +| Align - right | basic | ❌ | ❌ | +| Align - top | basic | ❌ | ❌ | +| Align - center | basic | ❌ | ❌ | +| Align - bottom | basic | ❌ | ❌ | +| Align - wrap text | basic | ❌ | ❌ | +| Align - rotation 45 | basic | ❌ | ❌ | +| Align - indent 2 | basic | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Align - left | basic | ❌ | +| Align - center | basic | ❌ | +| Align - right | basic | ❌ | +| Align - top | basic | ❌ | +| Align - center | basic | ❌ | +| Align - bottom | basic | ❌ | +| Align - wrap text | basic | ❌ | +| Align - rotation 45 | basic | ❌ | +| Align - indent 2 | basic | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Align - left | basic | ❌ | ❌ | +| Align - center | basic | ❌ | ❌ | +| Align - right | basic | ❌ | ❌ | +| Align - top | basic | ❌ | ❌ | +| Align - center | basic | ❌ | ❌ | +| Align - bottom | basic | ❌ | ❌ | +| Align - wrap text | basic | ❌ | ❌ | +| Align - rotation 45 | basic | ❌ | ❌ | +| Align - indent 2 | basic | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 +- Notes: Known limitation: pylightxl alignment write is a no-op because the library does not support formatting writes. + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Align - left | basic | ❌ | ❌ | +| Align - center | basic | ❌ | ❌ | +| Align - right | basic | ❌ | ❌ | +| Align - top | basic | ❌ | ❌ | +| Align - center | basic | ❌ | ❌ | +| Align - bottom | basic | ❌ | ❌ | +| Align - wrap text | basic | ❌ | ❌ | +| Align - rotation 45 | basic | ❌ | ❌ | +| Align - indent 2 | basic | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 +- Notes: Known limitation: python-calamine alignment read is limited because its API does not expose style/alignment metadata. + +| Test | Importance | Read | +|------|-----------|------| +| Align - left | basic | ❌ | +| Align - center | basic | ❌ | +| Align - right | basic | ❌ | +| Align - top | basic | ❌ | +| Align - center | basic | ❌ | +| Align - bottom | basic | ❌ | +| Align - wrap text | basic | ❌ | +| Align - rotation 45 | basic | ❌ | +| Align - indent 2 | basic | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Align - left | basic | ❌ | ❌ | +| Align - center | basic | ❌ | ❌ | +| Align - right | basic | ❌ | ❌ | +| Align - top | basic | ❌ | ❌ | +| Align - center | basic | ❌ | ❌ | +| Align - bottom | basic | ❌ | ❌ | +| Align - wrap text | basic | ❌ | ❌ | +| Align - rotation 45 | basic | ❌ | ❌ | +| Align - indent 2 | basic | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟠 1 + +| Test | Importance | Write | +|------|-----------|-------| +| Align - left | basic | ✅ | +| Align - center | basic | ✅ | +| Align - right | basic | ✅ | +| Align - top | basic | ✅ | +| Align - center | basic | ✅ | +| Align - bottom | basic | ❌ | +| Align - wrap text | basic | ✅ | +| Align - rotation 45 | basic | ✅ | +| Align - indent 2 | basic | ✅ | + +**xlsxwriter-constmem** — Write: 🟠 1 + +| Test | Importance | Write | +|------|-----------|-------| +| Align - left | basic | ✅ | +| Align - center | basic | ✅ | +| Align - right | basic | ✅ | +| Align - top | basic | ✅ | +| Align - center | basic | ✅ | +| Align - bottom | basic | ❌ | +| Align - wrap text | basic | ✅ | +| Align - rotation 45 | basic | ✅ | +| Align - indent 2 | basic | ✅ | + +**xlwt** — Write: 🟢 3 + + +### background_colors + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Background - red | basic | ❌ | +| Background - blue | basic | ❌ | +| Background - green | basic | ❌ | +| Background - custom (#8B4513) | basic | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Background - red | basic | ❌ | ❌ | +| Background - blue | basic | ❌ | ❌ | +| Background - green | basic | ❌ | ❌ | +| Background - custom (#8B4513) | basic | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Background - red | basic | ❌ | +| Background - blue | basic | ❌ | +| Background - green | basic | ❌ | +| Background - custom (#8B4513) | basic | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Background - red | basic | ❌ | ❌ | +| Background - blue | basic | ❌ | ❌ | +| Background - green | basic | ❌ | ❌ | +| Background - custom (#8B4513) | basic | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Background - red | basic | ❌ | ❌ | +| Background - blue | basic | ❌ | ❌ | +| Background - green | basic | ❌ | ❌ | +| Background - custom (#8B4513) | basic | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Background - red | basic | ❌ | +| Background - blue | basic | ❌ | +| Background - green | basic | ❌ | +| Background - custom (#8B4513) | basic | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Background - red | basic | ❌ | ❌ | +| Background - blue | basic | ❌ | ❌ | +| Background - green | basic | ❌ | ❌ | +| Background - custom (#8B4513) | basic | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🟠 1 + +| Test | Importance | Write | +|------|-----------|-------| +| Background - red | basic | ✅ | +| Background - blue | basic | ✅ | +| Background - green | basic | ❌ | +| Background - custom (#8B4513) | basic | ❌ | + + +### borders + +**aspose-cells-foss** — Read: 🟠 1 | Write: 🟠 1 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Border - thin all edges | basic | ✅ | ✅ | +| Border - medium all edges | basic | ✅ | ✅ | +| Border - thick all edges | basic | ✅ | ✅ | +| Border - double line | basic | ✅ | ✅ | +| Border - dashed | basic | ✅ | ✅ | +| Border - dotted | basic | ✅ | ✅ | +| Border - dash-dot | basic | ✅ | ✅ | +| Border - dash-dot-dot | basic | ✅ | ✅ | +| Border - top only | basic | ✅ | ✅ | +| Border - bottom only | basic | ✅ | ✅ | +| Border - left only | basic | ✅ | ✅ | +| Border - right only | basic | ✅ | ✅ | +| Border - diagonal up | basic | ❌ | ❌ | +| Border - diagonal down | basic | ❌ | ❌ | +| Border - diagonal both | basic | ❌ | ❌ | +| Border - red color | basic | ✅ | ✅ | +| Border - blue color | basic | ✅ | ✅ | +| Border - custom color (#8B4513) | basic | ✅ | ✅ | +| Border - mixed styles per edge | basic | ✅ | ✅ | +| Border - mixed colors per edge | basic | ✅ | ✅ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Border - thin all edges | basic | ❌ | +| Border - medium all edges | basic | ❌ | +| Border - thick all edges | basic | ❌ | +| Border - double line | basic | ❌ | +| Border - dashed | basic | ❌ | +| Border - dotted | basic | ❌ | +| Border - dash-dot | basic | ❌ | +| Border - dash-dot-dot | basic | ❌ | +| Border - top only | basic | ❌ | +| Border - bottom only | basic | ❌ | +| Border - left only | basic | ❌ | +| Border - right only | basic | ❌ | +| Border - diagonal up | basic | ❌ | +| Border - diagonal down | basic | ❌ | +| Border - diagonal both | basic | ❌ | +| Border - red color | basic | ❌ | +| Border - blue color | basic | ❌ | +| Border - custom color (#8B4513) | basic | ❌ | +| Border - mixed styles per edge | basic | ❌ | +| Border - mixed colors per edge | basic | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Border - thin all edges | basic | ❌ | ❌ | +| Border - medium all edges | basic | ❌ | ❌ | +| Border - thick all edges | basic | ❌ | ❌ | +| Border - double line | basic | ❌ | ❌ | +| Border - dashed | basic | ❌ | ❌ | +| Border - dotted | basic | ❌ | ❌ | +| Border - dash-dot | basic | ❌ | ❌ | +| Border - dash-dot-dot | basic | ❌ | ❌ | +| Border - top only | basic | ❌ | ❌ | +| Border - bottom only | basic | ❌ | ❌ | +| Border - left only | basic | ❌ | ❌ | +| Border - right only | basic | ❌ | ❌ | +| Border - diagonal up | basic | ❌ | ❌ | +| Border - diagonal down | basic | ❌ | ❌ | +| Border - diagonal both | basic | ❌ | ❌ | +| Border - red color | basic | ❌ | ❌ | +| Border - blue color | basic | ❌ | ❌ | +| Border - custom color (#8B4513) | basic | ❌ | ❌ | +| Border - mixed styles per edge | basic | ❌ | ❌ | +| Border - mixed colors per edge | basic | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Border - thin all edges | basic | ❌ | +| Border - medium all edges | basic | ❌ | +| Border - thick all edges | basic | ❌ | +| Border - double line | basic | ❌ | +| Border - dashed | basic | ❌ | +| Border - dotted | basic | ❌ | +| Border - dash-dot | basic | ❌ | +| Border - dash-dot-dot | basic | ❌ | +| Border - top only | basic | ❌ | +| Border - bottom only | basic | ❌ | +| Border - left only | basic | ❌ | +| Border - right only | basic | ❌ | +| Border - diagonal up | basic | ❌ | +| Border - diagonal down | basic | ❌ | +| Border - diagonal both | basic | ❌ | +| Border - red color | basic | ❌ | +| Border - blue color | basic | ❌ | +| Border - custom color (#8B4513) | basic | ❌ | +| Border - mixed styles per edge | basic | ❌ | +| Border - mixed colors per edge | basic | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Border - thin all edges | basic | ❌ | ❌ | +| Border - medium all edges | basic | ❌ | ❌ | +| Border - thick all edges | basic | ❌ | ❌ | +| Border - double line | basic | ❌ | ❌ | +| Border - dashed | basic | ❌ | ❌ | +| Border - dotted | basic | ❌ | ❌ | +| Border - dash-dot | basic | ❌ | ❌ | +| Border - dash-dot-dot | basic | ❌ | ❌ | +| Border - top only | basic | ❌ | ❌ | +| Border - bottom only | basic | ❌ | ❌ | +| Border - left only | basic | ❌ | ❌ | +| Border - right only | basic | ❌ | ❌ | +| Border - diagonal up | basic | ❌ | ❌ | +| Border - diagonal down | basic | ❌ | ❌ | +| Border - diagonal both | basic | ❌ | ❌ | +| Border - red color | basic | ❌ | ❌ | +| Border - blue color | basic | ❌ | ❌ | +| Border - custom color (#8B4513) | basic | ❌ | ❌ | +| Border - mixed styles per edge | basic | ❌ | ❌ | +| Border - mixed colors per edge | basic | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Border - thin all edges | basic | ❌ | ❌ | +| Border - medium all edges | basic | ❌ | ❌ | +| Border - thick all edges | basic | ❌ | ❌ | +| Border - double line | basic | ❌ | ❌ | +| Border - dashed | basic | ❌ | ❌ | +| Border - dotted | basic | ❌ | ❌ | +| Border - dash-dot | basic | ❌ | ❌ | +| Border - dash-dot-dot | basic | ❌ | ❌ | +| Border - top only | basic | ❌ | ❌ | +| Border - bottom only | basic | ❌ | ❌ | +| Border - left only | basic | ❌ | ❌ | +| Border - right only | basic | ❌ | ❌ | +| Border - diagonal up | basic | ❌ | ❌ | +| Border - diagonal down | basic | ❌ | ❌ | +| Border - diagonal both | basic | ❌ | ❌ | +| Border - red color | basic | ❌ | ❌ | +| Border - blue color | basic | ❌ | ❌ | +| Border - custom color (#8B4513) | basic | ❌ | ❌ | +| Border - mixed styles per edge | basic | ❌ | ❌ | +| Border - mixed colors per edge | basic | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Border - thin all edges | basic | ❌ | +| Border - medium all edges | basic | ❌ | +| Border - thick all edges | basic | ❌ | +| Border - double line | basic | ❌ | +| Border - dashed | basic | ❌ | +| Border - dotted | basic | ❌ | +| Border - dash-dot | basic | ❌ | +| Border - dash-dot-dot | basic | ❌ | +| Border - top only | basic | ❌ | +| Border - bottom only | basic | ❌ | +| Border - left only | basic | ❌ | +| Border - right only | basic | ❌ | +| Border - diagonal up | basic | ❌ | +| Border - diagonal down | basic | ❌ | +| Border - diagonal both | basic | ❌ | +| Border - red color | basic | ❌ | +| Border - blue color | basic | ❌ | +| Border - custom color (#8B4513) | basic | ❌ | +| Border - mixed styles per edge | basic | ❌ | +| Border - mixed colors per edge | basic | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Border - thin all edges | basic | ❌ | ❌ | +| Border - medium all edges | basic | ❌ | ❌ | +| Border - thick all edges | basic | ❌ | ❌ | +| Border - double line | basic | ❌ | ❌ | +| Border - dashed | basic | ❌ | ❌ | +| Border - dotted | basic | ❌ | ❌ | +| Border - dash-dot | basic | ❌ | ❌ | +| Border - dash-dot-dot | basic | ❌ | ❌ | +| Border - top only | basic | ❌ | ❌ | +| Border - bottom only | basic | ❌ | ❌ | +| Border - left only | basic | ❌ | ❌ | +| Border - right only | basic | ❌ | ❌ | +| Border - diagonal up | basic | ❌ | ❌ | +| Border - diagonal down | basic | ❌ | ❌ | +| Border - diagonal both | basic | ❌ | ❌ | +| Border - red color | basic | ❌ | ❌ | +| Border - blue color | basic | ❌ | ❌ | +| Border - custom color (#8B4513) | basic | ❌ | ❌ | +| Border - mixed styles per edge | basic | ❌ | ❌ | +| Border - mixed colors per edge | basic | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🟠 1 + +| Test | Importance | Write | +|------|-----------|-------| +| Border - thin all edges | basic | ✅ | +| Border - medium all edges | basic | ✅ | +| Border - thick all edges | basic | ✅ | +| Border - double line | basic | ✅ | +| Border - dashed | basic | ✅ | +| Border - dotted | basic | ✅ | +| Border - dash-dot | basic | ✅ | +| Border - dash-dot-dot | basic | ✅ | +| Border - top only | basic | ✅ | +| Border - bottom only | basic | ✅ | +| Border - left only | basic | ✅ | +| Border - right only | basic | ✅ | +| Border - diagonal up | basic | ❌ | +| Border - diagonal down | basic | ❌ | +| Border - diagonal both | basic | ✅ | +| Border - red color | basic | ✅ | +| Border - blue color | basic | ✅ | +| Border - custom color (#8B4513) | basic | ❌ | +| Border - mixed styles per edge | basic | ✅ | +| Border - mixed colors per edge | basic | ❌ | + + +### cell_values + +**aspose-cells-foss** — Read: 🟠 1 | Write: 🟢 3 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| String - simple | basic | ✅ | ✅ | +| String - unicode | basic | ✅ | ✅ | +| String - empty | basic | ✅ | ✅ | +| String - long (1000 chars) | basic | ✅ | ✅ | +| String - with newlines | basic | ✅ | ✅ | +| Number - integer | basic | ✅ | ✅ | +| Number - float | basic | ✅ | ✅ | +| Number - negative | basic | ✅ | ✅ | +| Number - large | basic | ✅ | ✅ | +| Number - scientific notation | basic | ✅ | ✅ | +| Date - standard | basic | ❌ | ✅ | +| DateTime - with time | basic | ❌ | ✅ | +| Boolean - TRUE | basic | ✅ | ✅ | +| Boolean - FALSE | basic | ✅ | ✅ | +| Error - #DIV/0! | basic | ✅ | ✅ | +| Error - #N/A | basic | ✅ | ✅ | +| Error - #VALUE! | basic | ✅ | ✅ | +| Blank cell | basic | ✅ | ✅ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🟢 3 + +**pandas** — Read: 🟠 1 | Write: 🟢 3 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| String - simple | basic | ✅ | ✅ | +| String - unicode | basic | ✅ | ✅ | +| String - empty | basic | ✅ | ✅ | +| String - long (1000 chars) | basic | ✅ | ✅ | +| String - with newlines | basic | ✅ | ✅ | +| Number - integer | basic | ✅ | ✅ | +| Number - float | basic | ✅ | ✅ | +| Number - negative | basic | ✅ | ✅ | +| Number - large | basic | ✅ | ✅ | +| Number - scientific notation | basic | ✅ | ✅ | +| Date - standard | basic | ✅ | ✅ | +| DateTime - with time | basic | ✅ | ✅ | +| Boolean - TRUE | basic | ✅ | ✅ | +| Boolean - FALSE | basic | ✅ | ✅ | +| Error - #DIV/0! | basic | ❌ | ✅ | +| Error - #N/A | basic | ❌ | ✅ | +| Error - #VALUE! | basic | ❌ | ✅ | +| Blank cell | basic | ✅ | ✅ | + +**polars** — Read: 🟠 1 + +| Test | Importance | Read | +|------|-----------|------| +| String - simple | basic | ✅ | +| String - unicode | basic | ✅ | +| String - empty | basic | ✅ | +| String - long (1000 chars) | basic | ✅ | +| String - with newlines | basic | ✅ | +| Number - integer | basic | ✅ | +| Number - float | basic | ✅ | +| Number - negative | basic | ✅ | +| Number - large | basic | ✅ | +| Number - scientific notation | basic | ✅ | +| Date - standard | basic | ✅ | +| DateTime - with time | basic | ✅ | +| Boolean - TRUE | basic | ✅ | +| Boolean - FALSE | basic | ✅ | +| Error - #DIV/0! | basic | ❌ | +| Error - #N/A | basic | ❌ | +| Error - #VALUE! | basic | ❌ | +| Blank cell | basic | ✅ | + +**pyexcel** — Read: 🟢 3 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| String - simple | basic | ✅ | ❌ | +| String - unicode | basic | ✅ | ❌ | +| String - empty | basic | ✅ | ❌ | +| String - long (1000 chars) | basic | ✅ | ❌ | +| String - with newlines | basic | ✅ | ❌ | +| Number - integer | basic | ✅ | ❌ | +| Number - float | basic | ✅ | ❌ | +| Number - negative | basic | ✅ | ❌ | +| Number - large | basic | ✅ | ❌ | +| Number - scientific notation | basic | ✅ | ❌ | +| Date - standard | basic | ✅ | ❌ | +| DateTime - with time | basic | ✅ | ❌ | +| Boolean - TRUE | basic | ✅ | ❌ | +| Boolean - FALSE | basic | ✅ | ❌ | +| Error - #DIV/0! | basic | ✅ | ❌ | +| Error - #N/A | basic | ✅ | ❌ | +| Error - #VALUE! | basic | ✅ | ❌ | +| Blank cell | basic | ✅ | ❌ | + +**pylightxl** — Read: 🟢 3 | Write: 🔴 0 +- Notes: Known limitation: pylightxl cell-values write has date/boolean/error fidelity limits due to writer encoding behavior. + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| String - simple | basic | ✅ | ❌ | +| String - unicode | basic | ✅ | ❌ | +| String - empty | basic | ✅ | ❌ | +| String - long (1000 chars) | basic | ✅ | ❌ | +| String - with newlines | basic | ✅ | ❌ | +| Number - integer | basic | ✅ | ❌ | +| Number - float | basic | ✅ | ❌ | +| Number - negative | basic | ✅ | ❌ | +| Number - large | basic | ✅ | ❌ | +| Number - scientific notation | basic | ✅ | ❌ | +| Date - standard | basic | ✅ | ❌ | +| DateTime - with time | basic | ✅ | ❌ | +| Boolean - TRUE | basic | ✅ | ❌ | +| Boolean - FALSE | basic | ✅ | ❌ | +| Error - #DIV/0! | basic | ✅ | ❌ | +| Error - #N/A | basic | ✅ | ❌ | +| Error - #VALUE! | basic | ✅ | ❌ | +| Blank cell | basic | ✅ | ❌ | + +**python-calamine** — Read: 🟠 1 +- Notes: Known limitation: python-calamine can surface formula error cells as blank values in current API responses. + +| Test | Importance | Read | +|------|-----------|------| +| String - simple | basic | ✅ | +| String - unicode | basic | ✅ | +| String - empty | basic | ✅ | +| String - long (1000 chars) | basic | ✅ | +| String - with newlines | basic | ✅ | +| Number - integer | basic | ✅ | +| Number - float | basic | ✅ | +| Number - negative | basic | ✅ | +| Number - large | basic | ✅ | +| Number - scientific notation | basic | ✅ | +| Date - standard | basic | ✅ | +| DateTime - with time | basic | ✅ | +| Boolean - TRUE | basic | ✅ | +| Boolean - FALSE | basic | ✅ | +| Error - #DIV/0! | basic | ❌ | +| Error - #N/A | basic | ❌ | +| Error - #VALUE! | basic | ❌ | +| Blank cell | basic | ✅ | + +**tablib** — Read: 🟢 3 | Write: 🟢 3 + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🟢 3 + + +### chart_anchor + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Chart: bar with twoCell anchor | basic | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Chart: bar with twoCell anchor | basic | ❌ | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Chart: bar with twoCell anchor | basic | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Chart: bar with twoCell anchor | basic | ❌ | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Chart: bar with twoCell anchor | basic | ❌ | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Chart: bar with twoCell anchor | basic | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Chart: bar with twoCell anchor | basic | ❌ | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Chart: bar with twoCell anchor | basic | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | + +**xlsxwriter-constmem** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Chart: bar with twoCell anchor | basic | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Chart: bar with twoCell anchor | basic | ❌ | +| Chart: line with twoCell anchor | edge | ❌ | + + +### comments + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Comment: legacy note | basic | ✅ | ❌ | +| Comment: threaded | edge | ✅ | ❌ | +| Comment: second author | edge | ✅ | ❌ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Comment: legacy note | basic | ❌ | +| Comment: threaded | edge | ❌ | +| Comment: second author | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Comment: legacy note | basic | ❌ | ❌ | +| Comment: threaded | edge | ❌ | ❌ | +| Comment: second author | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Comment: legacy note | basic | ❌ | +| Comment: threaded | edge | ❌ | +| Comment: second author | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Comment: legacy note | basic | ❌ | ❌ | +| Comment: threaded | edge | ❌ | ❌ | +| Comment: second author | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Comment: legacy note | basic | ❌ | ❌ | +| Comment: threaded | edge | ❌ | ❌ | +| Comment: second author | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Comment: legacy note | basic | ❌ | +| Comment: threaded | edge | ❌ | +| Comment: second author | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Comment: legacy note | basic | ❌ | ❌ | +| Comment: threaded | edge | ❌ | ❌ | +| Comment: second author | edge | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Comment: legacy note | basic | ❌ | +| Comment: threaded | edge | ❌ | +| Comment: second author | edge | ❌ | + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Comment: legacy note | basic | ❌ | +| Comment: threaded | edge | ❌ | +| Comment: second author | edge | ❌ | + + +### conditional_formatting + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| CF: cell > 5 (yellow fill) | basic | ❌ | +| CF: formula rule with cross-sheet ref | edge | ❌ | +| CF: text contains | edge | ❌ | +| CF: data bar | edge | ❌ | +| CF: 3-color scale | edge | ❌ | +| CF: stop-if-true priority | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| CF: cell > 5 (yellow fill) | basic | ❌ | ❌ | +| CF: formula rule with cross-sheet ref | edge | ❌ | ❌ | +| CF: text contains | edge | ❌ | ❌ | +| CF: data bar | edge | ❌ | ❌ | +| CF: 3-color scale | edge | ❌ | ❌ | +| CF: stop-if-true priority | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| CF: cell > 5 (yellow fill) | basic | ❌ | +| CF: formula rule with cross-sheet ref | edge | ❌ | +| CF: text contains | edge | ❌ | +| CF: data bar | edge | ❌ | +| CF: 3-color scale | edge | ❌ | +| CF: stop-if-true priority | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| CF: cell > 5 (yellow fill) | basic | ❌ | ❌ | +| CF: formula rule with cross-sheet ref | edge | ❌ | ❌ | +| CF: text contains | edge | ❌ | ❌ | +| CF: data bar | edge | ❌ | ❌ | +| CF: 3-color scale | edge | ❌ | ❌ | +| CF: stop-if-true priority | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| CF: cell > 5 (yellow fill) | basic | ❌ | ❌ | +| CF: formula rule with cross-sheet ref | edge | ❌ | ❌ | +| CF: text contains | edge | ❌ | ❌ | +| CF: data bar | edge | ❌ | ❌ | +| CF: 3-color scale | edge | ❌ | ❌ | +| CF: stop-if-true priority | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| CF: cell > 5 (yellow fill) | basic | ❌ | +| CF: formula rule with cross-sheet ref | edge | ❌ | +| CF: text contains | edge | ❌ | +| CF: data bar | edge | ❌ | +| CF: 3-color scale | edge | ❌ | +| CF: stop-if-true priority | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| CF: cell > 5 (yellow fill) | basic | ❌ | ❌ | +| CF: formula rule with cross-sheet ref | edge | ❌ | ❌ | +| CF: text contains | edge | ❌ | ❌ | +| CF: data bar | edge | ❌ | ❌ | +| CF: 3-color scale | edge | ❌ | ❌ | +| CF: stop-if-true priority | edge | ❌ | ❌ | + +**wolfxl** — Read: 🔴 0 | Write: 🟢 3 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| CF: cell > 5 (yellow fill) | basic | ❌ | ✅ | +| CF: formula rule with cross-sheet ref | edge | ❌ | ✅ | +| CF: text contains | edge | ❌ | ✅ | +| CF: data bar | edge | ✅ | ✅ | +| CF: 3-color scale | edge | ✅ | ✅ | +| CF: stop-if-true priority | edge | ❌ | ✅ | + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| CF: cell > 5 (yellow fill) | basic | ❌ | +| CF: formula rule with cross-sheet ref | edge | ❌ | +| CF: text contains | edge | ❌ | +| CF: data bar | edge | ❌ | +| CF: 3-color scale | edge | ❌ | +| CF: stop-if-true priority | edge | ❌ | + + +### data_validation + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| DV: list from CSV | basic | ❌ | +| DV: list from range | edge | ❌ | +| DV: cross-sheet named range | edge | ❌ | +| DV: custom formula | edge | ❌ | +| DV: whole number with error | basic | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| DV: list from CSV | basic | ❌ | ❌ | +| DV: list from range | edge | ❌ | ❌ | +| DV: cross-sheet named range | edge | ❌ | ❌ | +| DV: custom formula | edge | ❌ | ❌ | +| DV: whole number with error | basic | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| DV: list from CSV | basic | ❌ | +| DV: list from range | edge | ❌ | +| DV: cross-sheet named range | edge | ❌ | +| DV: custom formula | edge | ❌ | +| DV: whole number with error | basic | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| DV: list from CSV | basic | ❌ | ❌ | +| DV: list from range | edge | ❌ | ❌ | +| DV: cross-sheet named range | edge | ❌ | ❌ | +| DV: custom formula | edge | ❌ | ❌ | +| DV: whole number with error | basic | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| DV: list from CSV | basic | ❌ | ❌ | +| DV: list from range | edge | ❌ | ❌ | +| DV: cross-sheet named range | edge | ❌ | ❌ | +| DV: custom formula | edge | ❌ | ❌ | +| DV: whole number with error | basic | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| DV: list from CSV | basic | ❌ | +| DV: list from range | edge | ❌ | +| DV: cross-sheet named range | edge | ❌ | +| DV: custom formula | edge | ❌ | +| DV: whole number with error | basic | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| DV: list from CSV | basic | ❌ | ❌ | +| DV: list from range | edge | ❌ | ❌ | +| DV: cross-sheet named range | edge | ❌ | ❌ | +| DV: custom formula | edge | ❌ | ❌ | +| DV: whole number with error | basic | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| DV: list from CSV | basic | ❌ | +| DV: list from range | edge | ❌ | +| DV: cross-sheet named range | edge | ❌ | +| DV: custom formula | edge | ❌ | +| DV: whole number with error | basic | ❌ | + + +### dimensions + +**aspose-cells-foss** — Read: 🟠 1 | Write: 🟢 3 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Row height - 30 | basic | ✅ | ✅ | +| Row height - 45 | basic | ✅ | ✅ | +| Column width - D = 20 | basic | ❌ | ✅ | +| Column width - E = 8 | basic | ❌ | ✅ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Row height - 30 | basic | ❌ | +| Row height - 45 | basic | ❌ | +| Column width - D = 20 | basic | ❌ | +| Column width - E = 8 | basic | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Row height - 30 | basic | ❌ | ❌ | +| Row height - 45 | basic | ❌ | ❌ | +| Column width - D = 20 | basic | ❌ | ❌ | +| Column width - E = 8 | basic | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Row height - 30 | basic | ❌ | +| Row height - 45 | basic | ❌ | +| Column width - D = 20 | basic | ❌ | +| Column width - E = 8 | basic | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Row height - 30 | basic | ❌ | ❌ | +| Row height - 45 | basic | ❌ | ❌ | +| Column width - D = 20 | basic | ❌ | ❌ | +| Column width - E = 8 | basic | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Row height - 30 | basic | ❌ | ❌ | +| Row height - 45 | basic | ❌ | ❌ | +| Column width - D = 20 | basic | ❌ | ❌ | +| Column width - E = 8 | basic | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Row height - 30 | basic | ❌ | +| Row height - 45 | basic | ❌ | +| Column width - D = 20 | basic | ❌ | +| Column width - E = 8 | basic | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Row height - 30 | basic | ❌ | ❌ | +| Row height - 45 | basic | ❌ | ❌ | +| Column width - D = 20 | basic | ❌ | ❌ | +| Column width - E = 8 | basic | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟠 1 + +| Test | Importance | Write | +|------|-----------|-------| +| Row height - 30 | basic | ❌ | +| Row height - 45 | basic | ❌ | +| Column width - D = 20 | basic | ✅ | +| Column width - E = 8 | basic | ✅ | + +**xlwt** — Write: 🟠 1 + +| Test | Importance | Write | +|------|-----------|-------| +| Row height - 30 | basic | ❌ | +| Row height - 45 | basic | ❌ | +| Column width - D = 20 | basic | ✅ | +| Column width - E = 8 | basic | ✅ | + + +### formulas + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🟢 3 + +**pandas** — Read: 🔴 0 | Write: 🟢 3 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Formula - SUM | basic | ❌ | ✅ | +| Formula - cell reference | basic | ❌ | ✅ | +| Formula - concat | basic | ❌ | ✅ | +| Formula - cross sheet | basic | ❌ | ✅ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Formula - SUM | basic | ❌ | +| Formula - cell reference | basic | ❌ | +| Formula - concat | basic | ❌ | +| Formula - cross sheet | basic | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🟢 3 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Formula - SUM | basic | ❌ | ✅ | +| Formula - cell reference | basic | ❌ | ✅ | +| Formula - concat | basic | ❌ | ✅ | +| Formula - cross sheet | basic | ❌ | ✅ | + +**pylightxl** — Read: 🔴 0 | Write: 🟢 3 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Formula - SUM | basic | ❌ | ✅ | +| Formula - cell reference | basic | ❌ | ✅ | +| Formula - concat | basic | ❌ | ✅ | +| Formula - cross sheet | basic | ❌ | ✅ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Formula - SUM | basic | ❌ | +| Formula - cell reference | basic | ❌ | +| Formula - concat | basic | ❌ | +| Formula - cross sheet | basic | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🟢 3 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Formula - SUM | basic | ❌ | ✅ | +| Formula - cell reference | basic | ❌ | ✅ | +| Formula - concat | basic | ❌ | ✅ | +| Formula - cross sheet | basic | ❌ | ✅ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Formula - SUM | basic | ❌ | +| Formula - cell reference | basic | ❌ | +| Formula - concat | basic | ❌ | +| Formula - cross sheet | basic | ❌ | + + +### freeze_panes + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Freeze panes at B2 | basic | ❌ | +| Freeze panes at D5 | edge | ❌ | +| Split panes row=2 col=1 | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Freeze panes at B2 | basic | ❌ | ❌ | +| Freeze panes at D5 | edge | ❌ | ❌ | +| Split panes row=2 col=1 | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Freeze panes at B2 | basic | ❌ | +| Freeze panes at D5 | edge | ❌ | +| Split panes row=2 col=1 | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Freeze panes at B2 | basic | ❌ | ❌ | +| Freeze panes at D5 | edge | ❌ | ❌ | +| Split panes row=2 col=1 | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Freeze panes at B2 | basic | ❌ | ❌ | +| Freeze panes at D5 | edge | ❌ | ❌ | +| Split panes row=2 col=1 | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Freeze panes at B2 | basic | ❌ | +| Freeze panes at D5 | edge | ❌ | +| Split panes row=2 col=1 | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Freeze panes at B2 | basic | ❌ | ❌ | +| Freeze panes at D5 | edge | ❌ | ❌ | +| Split panes row=2 col=1 | edge | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Freeze panes at B2 | basic | ❌ | +| Freeze panes at D5 | edge | ❌ | +| Split panes row=2 col=1 | edge | ❌ | + + +### hyperlinks + +**aspose-cells-foss** — Read: 🔴 0 | Write: 🟢 3 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Hyperlink: external URL | basic | ❌ | ✅ | +| Hyperlink: internal sheet | edge | ❌ | ✅ | +| Hyperlink: mailto | basic | ❌ | ✅ | +| Hyperlink: long encoded URL | edge | ❌ | ✅ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Hyperlink: external URL | basic | ❌ | +| Hyperlink: internal sheet | edge | ❌ | +| Hyperlink: mailto | basic | ❌ | +| Hyperlink: long encoded URL | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Hyperlink: external URL | basic | ❌ | ❌ | +| Hyperlink: internal sheet | edge | ❌ | ❌ | +| Hyperlink: mailto | basic | ❌ | ❌ | +| Hyperlink: long encoded URL | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Hyperlink: external URL | basic | ❌ | +| Hyperlink: internal sheet | edge | ❌ | +| Hyperlink: mailto | basic | ❌ | +| Hyperlink: long encoded URL | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Hyperlink: external URL | basic | ❌ | ❌ | +| Hyperlink: internal sheet | edge | ❌ | ❌ | +| Hyperlink: mailto | basic | ❌ | ❌ | +| Hyperlink: long encoded URL | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Hyperlink: external URL | basic | ❌ | ❌ | +| Hyperlink: internal sheet | edge | ❌ | ❌ | +| Hyperlink: mailto | basic | ❌ | ❌ | +| Hyperlink: long encoded URL | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Hyperlink: external URL | basic | ❌ | +| Hyperlink: internal sheet | edge | ❌ | +| Hyperlink: mailto | basic | ❌ | +| Hyperlink: long encoded URL | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Hyperlink: external URL | basic | ❌ | ❌ | +| Hyperlink: internal sheet | edge | ❌ | ❌ | +| Hyperlink: mailto | basic | ❌ | ❌ | +| Hyperlink: long encoded URL | edge | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Hyperlink: external URL | basic | ❌ | +| Hyperlink: internal sheet | edge | ❌ | +| Hyperlink: mailto | basic | ❌ | +| Hyperlink: long encoded URL | edge | ❌ | + + +### images + +**aspose-cells-foss** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Image: one-cell anchor | basic | ❌ | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | ❌ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Image: one-cell anchor | basic | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Image: one-cell anchor | basic | ❌ | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Image: one-cell anchor | basic | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Image: one-cell anchor | basic | ❌ | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Image: one-cell anchor | basic | ❌ | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Image: one-cell anchor | basic | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Image: one-cell anchor | basic | ❌ | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Image: one-cell anchor | basic | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Image: one-cell anchor | basic | ❌ | +| Image: two-cell anchor with offset | edge | ❌ | + + +### merged_cells + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Merge horizontal B2:D2 | basic | ❌ | +| Merge vertical B3:B5 | basic | ❌ | +| Merge with non-top-left value | edge | ❌ | +| Merge with top-left fill | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Merge horizontal B2:D2 | basic | ❌ | ❌ | +| Merge vertical B3:B5 | basic | ❌ | ❌ | +| Merge with non-top-left value | edge | ❌ | ❌ | +| Merge with top-left fill | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Merge horizontal B2:D2 | basic | ❌ | +| Merge vertical B3:B5 | basic | ❌ | +| Merge with non-top-left value | edge | ❌ | +| Merge with top-left fill | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Merge horizontal B2:D2 | basic | ❌ | ❌ | +| Merge vertical B3:B5 | basic | ❌ | ❌ | +| Merge with non-top-left value | edge | ❌ | ❌ | +| Merge with top-left fill | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Merge horizontal B2:D2 | basic | ❌ | ❌ | +| Merge vertical B3:B5 | basic | ❌ | ❌ | +| Merge with non-top-left value | edge | ❌ | ❌ | +| Merge with top-left fill | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Merge horizontal B2:D2 | basic | ❌ | +| Merge vertical B3:B5 | basic | ❌ | +| Merge with non-top-left value | edge | ❌ | +| Merge with top-left fill | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Merge horizontal B2:D2 | basic | ❌ | ❌ | +| Merge vertical B3:B5 | basic | ❌ | ❌ | +| Merge with non-top-left value | edge | ❌ | ❌ | +| Merge with top-left fill | edge | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Merge horizontal B2:D2 | basic | ❌ | +| Merge vertical B3:B5 | basic | ❌ | +| Merge with non-top-left value | edge | ❌ | +| Merge with top-left fill | edge | ❌ | + + +### multiple_sheets + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🟢 3 + +**pandas** — Read: 🟢 3 | Write: 🟢 3 + +**polars** — Read: 🟠 1 + +| Test | Importance | Read | +|------|-----------|------| +| Sheet names | basic | ✅ | +| Alpha value | basic | ✅ | +| Beta value | basic | ❌ | +| Gamma value | basic | ❌ | + +**pyexcel** — Read: 🟢 3 | Write: 🟢 3 + +**pylightxl** — Read: 🟢 3 | Write: 🟢 3 + +**python-calamine** — Read: 🟢 3 + +**tablib** — Read: 🟢 3 | Write: 🟢 3 + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🟢 3 + + +### named_ranges + +**aspose-cells-foss** — Read: 🟡 2 | Write: 🟢 3 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Named range: single cell | basic | ✅ | ✅ | +| Named range: cell range | basic | ✅ | ✅ | +| Named range: used in formula | basic | ✅ | ✅ | +| Named range: sheet-scoped | edge | ❌ | ✅ | +| Named range: cross-sheet reference | edge | ✅ | ✅ | +| Named range: underscore name | edge | ✅ | ✅ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Named range: single cell | basic | ❌ | +| Named range: cell range | basic | ❌ | +| Named range: used in formula | basic | ❌ | +| Named range: sheet-scoped | edge | ❌ | +| Named range: cross-sheet reference | edge | ❌ | +| Named range: underscore name | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Named range: single cell | basic | ❌ | ❌ | +| Named range: cell range | basic | ❌ | ❌ | +| Named range: used in formula | basic | ❌ | ❌ | +| Named range: sheet-scoped | edge | ❌ | ❌ | +| Named range: cross-sheet reference | edge | ❌ | ❌ | +| Named range: underscore name | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Named range: single cell | basic | ❌ | +| Named range: cell range | basic | ❌ | +| Named range: used in formula | basic | ❌ | +| Named range: sheet-scoped | edge | ❌ | +| Named range: cross-sheet reference | edge | ❌ | +| Named range: underscore name | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Named range: single cell | basic | ❌ | ❌ | +| Named range: cell range | basic | ❌ | ❌ | +| Named range: used in formula | basic | ❌ | ❌ | +| Named range: sheet-scoped | edge | ❌ | ❌ | +| Named range: cross-sheet reference | edge | ❌ | ❌ | +| Named range: underscore name | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Named range: single cell | basic | ❌ | ❌ | +| Named range: cell range | basic | ❌ | ❌ | +| Named range: used in formula | basic | ❌ | ❌ | +| Named range: sheet-scoped | edge | ❌ | ❌ | +| Named range: cross-sheet reference | edge | ❌ | ❌ | +| Named range: underscore name | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Named range: single cell | basic | ❌ | +| Named range: cell range | basic | ❌ | +| Named range: used in formula | basic | ❌ | +| Named range: sheet-scoped | edge | ❌ | +| Named range: cross-sheet reference | edge | ❌ | +| Named range: underscore name | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Named range: single cell | basic | ❌ | ❌ | +| Named range: cell range | basic | ❌ | ❌ | +| Named range: used in formula | basic | ❌ | ❌ | +| Named range: sheet-scoped | edge | ❌ | ❌ | +| Named range: cross-sheet reference | edge | ❌ | ❌ | +| Named range: underscore name | edge | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟡 2 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Named range: single cell | basic | ✅ | ✅ | +| Named range: cell range | basic | ✅ | ✅ | +| Named range: used in formula | basic | ✅ | ✅ | +| Named range: sheet-scoped | edge | ✅ | ❌ | +| Named range: cross-sheet reference | edge | ✅ | ✅ | +| Named range: underscore name | edge | ✅ | ✅ | + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Named range: single cell | basic | ❌ | +| Named range: cell range | basic | ❌ | +| Named range: used in formula | basic | ❌ | +| Named range: sheet-scoped | edge | ❌ | +| Named range: cross-sheet reference | edge | ❌ | +| Named range: underscore name | edge | ❌ | + +**xlsxwriter-constmem** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Named range: single cell | basic | ❌ | +| Named range: cell range | basic | ❌ | +| Named range: used in formula | basic | ❌ | +| Named range: sheet-scoped | edge | ❌ | +| Named range: cross-sheet reference | edge | ❌ | +| Named range: underscore name | edge | ❌ | + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Named range: single cell | basic | ❌ | +| Named range: cell range | basic | ❌ | +| Named range: used in formula | basic | ❌ | +| Named range: sheet-scoped | edge | ❌ | +| Named range: cross-sheet reference | edge | ❌ | +| Named range: underscore name | edge | ❌ | + + +### number_formats + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Format - currency | basic | ❌ | +| Format - percent | basic | ❌ | +| Format - date | basic | ❌ | +| Format - scientific | basic | ❌ | +| Format - custom text | basic | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Format - currency | basic | ❌ | ❌ | +| Format - percent | basic | ❌ | ❌ | +| Format - date | basic | ❌ | ❌ | +| Format - scientific | basic | ❌ | ❌ | +| Format - custom text | basic | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Format - currency | basic | ❌ | +| Format - percent | basic | ❌ | +| Format - date | basic | ❌ | +| Format - scientific | basic | ❌ | +| Format - custom text | basic | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Format - currency | basic | ❌ | ❌ | +| Format - percent | basic | ❌ | ❌ | +| Format - date | basic | ❌ | ❌ | +| Format - scientific | basic | ❌ | ❌ | +| Format - custom text | basic | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Format - currency | basic | ❌ | ❌ | +| Format - percent | basic | ❌ | ❌ | +| Format - date | basic | ❌ | ❌ | +| Format - scientific | basic | ❌ | ❌ | +| Format - custom text | basic | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Format - currency | basic | ❌ | +| Format - percent | basic | ❌ | +| Format - date | basic | ❌ | +| Format - scientific | basic | ❌ | +| Format - custom text | basic | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Format - currency | basic | ❌ | ❌ | +| Format - percent | basic | ❌ | ❌ | +| Format - date | basic | ❌ | ❌ | +| Format - scientific | basic | ❌ | ❌ | +| Format - custom text | basic | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🟢 3 + + +### page_setup + +**aspose-cells-foss** — Read: 🟠 1 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Page setup: landscape + fit-to-width | basic | ❌ | ❌ | +| Page setup: portrait at 75% scale | basic | ✅ | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | ❌ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Page setup: landscape + fit-to-width | basic | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Page setup: landscape + fit-to-width | basic | ❌ | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Page setup: landscape + fit-to-width | basic | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Page setup: landscape + fit-to-width | basic | ❌ | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Page setup: landscape + fit-to-width | basic | ❌ | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Page setup: landscape + fit-to-width | basic | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Page setup: landscape + fit-to-width | basic | ❌ | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟡 2 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Page setup: landscape + fit-to-width | basic | ✅ | ✅ | +| Page setup: portrait at 75% scale | basic | ✅ | ✅ | +| Page setup: print titles + header/footer | edge | ✅ | ❌ | + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Page setup: landscape + fit-to-width | basic | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | + +**xlsxwriter-constmem** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Page setup: landscape + fit-to-width | basic | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Page setup: landscape + fit-to-width | basic | ❌ | +| Page setup: portrait at 75% scale | basic | ❌ | +| Page setup: print titles + header/footer | edge | ❌ | + + +### pivot_tables + +**aspose-cells-foss** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**openpyxl** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**openpyxl-readonly** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**pandas** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**polars** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**pyexcel** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**pylightxl** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**python-calamine** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**tablib** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**wolfxl** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**xlsxwriter-constmem** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + +**xlwt** +- Notes: Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx). + + +### sheet_protection + +**aspose-cells-foss** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Protection: basic (OOXML defaults) | basic | ❌ | +| Protection: with password hash | basic | ❌ | +| Protection: granular attribute flags | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Protection: basic (OOXML defaults) | basic | ❌ | ❌ | +| Protection: with password hash | basic | ❌ | ❌ | +| Protection: granular attribute flags | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Protection: basic (OOXML defaults) | basic | ❌ | +| Protection: with password hash | basic | ❌ | +| Protection: granular attribute flags | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Protection: basic (OOXML defaults) | basic | ❌ | ❌ | +| Protection: with password hash | basic | ❌ | ❌ | +| Protection: granular attribute flags | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Protection: basic (OOXML defaults) | basic | ❌ | ❌ | +| Protection: with password hash | basic | ❌ | ❌ | +| Protection: granular attribute flags | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Protection: basic (OOXML defaults) | basic | ❌ | +| Protection: with password hash | basic | ❌ | +| Protection: granular attribute flags | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Protection: basic (OOXML defaults) | basic | ❌ | ❌ | +| Protection: with password hash | basic | ❌ | ❌ | +| Protection: granular attribute flags | edge | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Protection: basic (OOXML defaults) | basic | ❌ | +| Protection: with password hash | basic | ❌ | +| Protection: granular attribute flags | edge | ❌ | + +**xlsxwriter-constmem** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Protection: basic (OOXML defaults) | basic | ❌ | +| Protection: with password hash | basic | ❌ | +| Protection: granular attribute flags | edge | ❌ | + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Protection: basic (OOXML defaults) | basic | ❌ | +| Protection: with password hash | basic | ❌ | +| Protection: granular attribute flags | edge | ❌ | + + +### tables + +**aspose-cells-foss** — Read: 🟠 1 | Write: 🟠 1 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Table: basic 3-col | basic | ✅ | ✅ | +| Table: with totals row | basic | ❌ | ❌ | +| Table: no style | basic | ❌ | ❌ | +| Table: single column | edge | ✅ | ✅ | +| Table: header only (no data rows) | edge | ✅ | ✅ | +| Table: with autoFilter | edge | ✅ | ✅ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Table: basic 3-col | basic | ❌ | +| Table: with totals row | basic | ❌ | +| Table: no style | basic | ❌ | +| Table: single column | edge | ❌ | +| Table: header only (no data rows) | edge | ❌ | +| Table: with autoFilter | edge | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Table: basic 3-col | basic | ❌ | ❌ | +| Table: with totals row | basic | ❌ | ❌ | +| Table: no style | basic | ❌ | ❌ | +| Table: single column | edge | ❌ | ❌ | +| Table: header only (no data rows) | edge | ❌ | ❌ | +| Table: with autoFilter | edge | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Table: basic 3-col | basic | ❌ | +| Table: with totals row | basic | ❌ | +| Table: no style | basic | ❌ | +| Table: single column | edge | ❌ | +| Table: header only (no data rows) | edge | ❌ | +| Table: with autoFilter | edge | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Table: basic 3-col | basic | ❌ | ❌ | +| Table: with totals row | basic | ❌ | ❌ | +| Table: no style | basic | ❌ | ❌ | +| Table: single column | edge | ❌ | ❌ | +| Table: header only (no data rows) | edge | ❌ | ❌ | +| Table: with autoFilter | edge | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Table: basic 3-col | basic | ❌ | ❌ | +| Table: with totals row | basic | ❌ | ❌ | +| Table: no style | basic | ❌ | ❌ | +| Table: single column | edge | ❌ | ❌ | +| Table: header only (no data rows) | edge | ❌ | ❌ | +| Table: with autoFilter | edge | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Table: basic 3-col | basic | ❌ | +| Table: with totals row | basic | ❌ | +| Table: no style | basic | ❌ | +| Table: single column | edge | ❌ | +| Table: header only (no data rows) | edge | ❌ | +| Table: with autoFilter | edge | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Table: basic 3-col | basic | ❌ | ❌ | +| Table: with totals row | basic | ❌ | ❌ | +| Table: no style | basic | ❌ | ❌ | +| Table: single column | edge | ❌ | ❌ | +| Table: header only (no data rows) | edge | ❌ | ❌ | +| Table: with autoFilter | edge | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Table: basic 3-col | basic | ❌ | +| Table: with totals row | basic | ❌ | +| Table: no style | basic | ❌ | +| Table: single column | edge | ❌ | +| Table: header only (no data rows) | edge | ❌ | +| Table: with autoFilter | edge | ❌ | + +**xlsxwriter-constmem** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Table: basic 3-col | basic | ❌ | +| Table: with totals row | basic | ❌ | +| Table: no style | basic | ❌ | +| Table: single column | edge | ❌ | +| Table: header only (no data rows) | edge | ❌ | +| Table: with autoFilter | edge | ❌ | + +**xlwt** — Write: 🔴 0 + +| Test | Importance | Write | +|------|-----------|-------| +| Table: basic 3-col | basic | ❌ | +| Table: with totals row | basic | ❌ | +| Table: no style | basic | ❌ | +| Table: single column | edge | ❌ | +| Table: header only (no data rows) | edge | ❌ | +| Table: with autoFilter | edge | ❌ | + + +### text_formatting + +**aspose-cells-foss** — Read: 🟠 1 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Bold | basic | ✅ | ❌ | +| Italic | basic | ✅ | ❌ | +| Underline - single | basic | ✅ | ❌ | +| Underline - double | basic | ❌ | ❌ | +| Strikethrough | basic | ✅ | ❌ | +| Bold + Italic | basic | ✅ | ❌ | +| Font size 8 | basic | ✅ | ❌ | +| Font size 14 | basic | ✅ | ❌ | +| Font size 24 | basic | ✅ | ❌ | +| Font size 36 | basic | ✅ | ❌ | +| Font - Arial | basic | ✅ | ❌ | +| Font - Times New Roman | basic | ✅ | ❌ | +| Font - Courier New | basic | ✅ | ❌ | +| Font color - red | basic | ✅ | ❌ | +| Font color - blue | basic | ✅ | ❌ | +| Font color - green | basic | ✅ | ❌ | +| Font color - custom (#8B4513) | basic | ✅ | ❌ | +| Combined - bold, 16pt, red | basic | ✅ | ❌ | + +**openpyxl** — Read: 🟢 3 | Write: 🟢 3 + +**openpyxl-readonly** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Bold | basic | ❌ | +| Italic | basic | ❌ | +| Underline - single | basic | ❌ | +| Underline - double | basic | ❌ | +| Strikethrough | basic | ❌ | +| Bold + Italic | basic | ❌ | +| Font size 8 | basic | ❌ | +| Font size 14 | basic | ❌ | +| Font size 24 | basic | ❌ | +| Font size 36 | basic | ❌ | +| Font - Arial | basic | ❌ | +| Font - Times New Roman | basic | ❌ | +| Font - Courier New | basic | ❌ | +| Font color - red | basic | ❌ | +| Font color - blue | basic | ❌ | +| Font color - green | basic | ❌ | +| Font color - custom (#8B4513) | basic | ❌ | +| Combined - bold, 16pt, red | basic | ❌ | + +**pandas** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Bold | basic | ❌ | ❌ | +| Italic | basic | ❌ | ❌ | +| Underline - single | basic | ❌ | ❌ | +| Underline - double | basic | ❌ | ❌ | +| Strikethrough | basic | ❌ | ❌ | +| Bold + Italic | basic | ❌ | ❌ | +| Font size 8 | basic | ❌ | ❌ | +| Font size 14 | basic | ❌ | ❌ | +| Font size 24 | basic | ❌ | ❌ | +| Font size 36 | basic | ❌ | ❌ | +| Font - Arial | basic | ❌ | ❌ | +| Font - Times New Roman | basic | ❌ | ❌ | +| Font - Courier New | basic | ❌ | ❌ | +| Font color - red | basic | ❌ | ❌ | +| Font color - blue | basic | ❌ | ❌ | +| Font color - green | basic | ❌ | ❌ | +| Font color - custom (#8B4513) | basic | ❌ | ❌ | +| Combined - bold, 16pt, red | basic | ❌ | ❌ | + +**polars** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Bold | basic | ❌ | +| Italic | basic | ❌ | +| Underline - single | basic | ❌ | +| Underline - double | basic | ❌ | +| Strikethrough | basic | ❌ | +| Bold + Italic | basic | ❌ | +| Font size 8 | basic | ❌ | +| Font size 14 | basic | ❌ | +| Font size 24 | basic | ❌ | +| Font size 36 | basic | ❌ | +| Font - Arial | basic | ❌ | +| Font - Times New Roman | basic | ❌ | +| Font - Courier New | basic | ❌ | +| Font color - red | basic | ❌ | +| Font color - blue | basic | ❌ | +| Font color - green | basic | ❌ | +| Font color - custom (#8B4513) | basic | ❌ | +| Combined - bold, 16pt, red | basic | ❌ | + +**pyexcel** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Bold | basic | ❌ | ❌ | +| Italic | basic | ❌ | ❌ | +| Underline - single | basic | ❌ | ❌ | +| Underline - double | basic | ❌ | ❌ | +| Strikethrough | basic | ❌ | ❌ | +| Bold + Italic | basic | ❌ | ❌ | +| Font size 8 | basic | ❌ | ❌ | +| Font size 14 | basic | ❌ | ❌ | +| Font size 24 | basic | ❌ | ❌ | +| Font size 36 | basic | ❌ | ❌ | +| Font - Arial | basic | ❌ | ❌ | +| Font - Times New Roman | basic | ❌ | ❌ | +| Font - Courier New | basic | ❌ | ❌ | +| Font color - red | basic | ❌ | ❌ | +| Font color - blue | basic | ❌ | ❌ | +| Font color - green | basic | ❌ | ❌ | +| Font color - custom (#8B4513) | basic | ❌ | ❌ | +| Combined - bold, 16pt, red | basic | ❌ | ❌ | + +**pylightxl** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Bold | basic | ❌ | ❌ | +| Italic | basic | ❌ | ❌ | +| Underline - single | basic | ❌ | ❌ | +| Underline - double | basic | ❌ | ❌ | +| Strikethrough | basic | ❌ | ❌ | +| Bold + Italic | basic | ❌ | ❌ | +| Font size 8 | basic | ❌ | ❌ | +| Font size 14 | basic | ❌ | ❌ | +| Font size 24 | basic | ❌ | ❌ | +| Font size 36 | basic | ❌ | ❌ | +| Font - Arial | basic | ❌ | ❌ | +| Font - Times New Roman | basic | ❌ | ❌ | +| Font - Courier New | basic | ❌ | ❌ | +| Font color - red | basic | ❌ | ❌ | +| Font color - blue | basic | ❌ | ❌ | +| Font color - green | basic | ❌ | ❌ | +| Font color - custom (#8B4513) | basic | ❌ | ❌ | +| Combined - bold, 16pt, red | basic | ❌ | ❌ | + +**python-calamine** — Read: 🔴 0 + +| Test | Importance | Read | +|------|-----------|------| +| Bold | basic | ❌ | +| Italic | basic | ❌ | +| Underline - single | basic | ❌ | +| Underline - double | basic | ❌ | +| Strikethrough | basic | ❌ | +| Bold + Italic | basic | ❌ | +| Font size 8 | basic | ❌ | +| Font size 14 | basic | ❌ | +| Font size 24 | basic | ❌ | +| Font size 36 | basic | ❌ | +| Font - Arial | basic | ❌ | +| Font - Times New Roman | basic | ❌ | +| Font - Courier New | basic | ❌ | +| Font color - red | basic | ❌ | +| Font color - blue | basic | ❌ | +| Font color - green | basic | ❌ | +| Font color - custom (#8B4513) | basic | ❌ | +| Combined - bold, 16pt, red | basic | ❌ | + +**tablib** — Read: 🔴 0 | Write: 🔴 0 + +| Test | Importance | Read | Write | +|------|-----------|------|-------| +| Bold | basic | ❌ | ❌ | +| Italic | basic | ❌ | ❌ | +| Underline - single | basic | ❌ | ❌ | +| Underline - double | basic | ❌ | ❌ | +| Strikethrough | basic | ❌ | ❌ | +| Bold + Italic | basic | ❌ | ❌ | +| Font size 8 | basic | ❌ | ❌ | +| Font size 14 | basic | ❌ | ❌ | +| Font size 24 | basic | ❌ | ❌ | +| Font size 36 | basic | ❌ | ❌ | +| Font - Arial | basic | ❌ | ❌ | +| Font - Times New Roman | basic | ❌ | ❌ | +| Font - Courier New | basic | ❌ | ❌ | +| Font color - red | basic | ❌ | ❌ | +| Font color - blue | basic | ❌ | ❌ | +| Font color - green | basic | ❌ | ❌ | +| Font color - custom (#8B4513) | basic | ❌ | ❌ | +| Combined - bold, 16pt, red | basic | ❌ | ❌ | + +**wolfxl** — Read: 🟢 3 | Write: 🟢 3 + +**xlrd** +- Notes: Not applicable: xlrd does not support .xlsx input + +**xlsxwriter** — Write: 🟢 3 + +**xlsxwriter-constmem** — Write: 🟢 3 + +**xlwt** — Write: 🟠 1 + +| Test | Importance | Write | +|------|-----------|-------| +| Bold | basic | ✅ | +| Italic | basic | ✅ | +| Underline - single | basic | ✅ | +| Underline - double | basic | ✅ | +| Strikethrough | basic | ✅ | +| Bold + Italic | basic | ✅ | +| Font size 8 | basic | ✅ | +| Font size 14 | basic | ✅ | +| Font size 24 | basic | ✅ | +| Font size 36 | basic | ✅ | +| Font - Arial | basic | ✅ | +| Font - Times New Roman | basic | ✅ | +| Font - Courier New | basic | ✅ | +| Font color - red | basic | ✅ | +| Font color - blue | basic | ✅ | +| Font color - green | basic | ❌ | +| Font color - custom (#8B4513) | basic | ❌ | +| Combined - bold, 16pt, red | basic | ✅ | + +--- +*Benchmark version: 0.1.0* \ No newline at end of file diff --git a/results-2026-09-08/xlsx/WHY_FAILED.md b/results-2026-09-08/xlsx/WHY_FAILED.md new file mode 100644 index 0000000..9cbfa87 --- /dev/null +++ b/results-2026-09-08/xlsx/WHY_FAILED.md @@ -0,0 +1,8497 @@ +# Why Failed + +## cell_values / python-calamine / read / error_div0 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## cell_values / python-calamine / read / error_na + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## cell_values / python-calamine / read / error_value + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## cell_values / aspose-cells-foss / read / date_standard + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## cell_values / aspose-cells-foss / read / datetime + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## cell_values / pylightxl / write / string_simple + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / string_unicode + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / string_empty + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / string_long + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / string_newline + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / number_integer + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / number_float + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / number_negative + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / number_large + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / number_scientific + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / date_standard + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / datetime + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / boolean_true + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / boolean_false + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / error_div0 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / error_na + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / error_value + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pylightxl / write / blank + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / string_simple + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / string_unicode + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / string_empty + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / string_long + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / string_newline + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / number_integer + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / number_float + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / number_negative + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / number_large + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / number_scientific + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / date_standard + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / datetime + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / boolean_true + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / boolean_false + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / error_div0 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / error_na + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / error_value + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pyexcel / write / blank + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## cell_values / pandas / read / error_div0 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## cell_values / pandas / read / error_na + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## cell_values / pandas / read / error_value + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## cell_values / polars / read / error_div0 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## cell_values / polars / read / error_na + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## cell_values / polars / read / error_value + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## formulas / python-calamine / read / formula_sum + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / python-calamine / read / formula_cell_ref + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / python-calamine / read / formula_concat + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / python-calamine / read / formula_cross_sheet + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pylightxl / read / formula_sum + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pylightxl / read / formula_cell_ref + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pylightxl / read / formula_concat + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pylightxl / read / formula_cross_sheet + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pyexcel / read / formula_sum + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pyexcel / read / formula_cell_ref + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pyexcel / read / formula_concat + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pyexcel / read / formula_cross_sheet + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / xlwt / write / formula_sum + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / xlwt / write / formula_cell_ref + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / xlwt / write / formula_concat + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / xlwt / write / formula_cross_sheet + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pandas / read / formula_sum + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pandas / read / formula_cell_ref + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pandas / read / formula_concat + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / pandas / read / formula_cross_sheet + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / polars / read / formula_sum + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / polars / read / formula_cell_ref + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / polars / read / formula_concat + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / polars / read / formula_cross_sheet + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / tablib / read / formula_sum + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / tablib / read / formula_cell_ref + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / tablib / read / formula_concat + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## formulas / tablib / read / formula_cross_sheet + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## text_formatting / python-calamine / read / bold + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / python-calamine / read / italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / python-calamine / read / underline_single + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / python-calamine / read / underline_double + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / python-calamine / read / strikethrough + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / python-calamine / read / bold_italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / python-calamine / read / font_size_8 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / font_size_14 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / font_size_24 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / font_size_36 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / font_arial + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / font_times + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / font_courier + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / color_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / python-calamine / read / combined + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / aspose-cells-foss / read / underline_double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / aspose-cells-foss / write / bold + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / italic + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / underline_single + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / underline_double + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / strikethrough + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / bold_italic + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / font_size_8 + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / font_size_14 + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / font_size_24 + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / font_size_36 + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / font_arial + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / font_times + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / font_courier + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / color_red + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / color_blue + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / color_green + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / color_custom + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / aspose-cells-foss / write / combined + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss supports only a single underline, not accounting or double variants. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / read / bold + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pylightxl / read / italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pylightxl / read / underline_single + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pylightxl / read / underline_double + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pylightxl / read / strikethrough + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pylightxl / read / bold_italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pylightxl / read / font_size_8 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / font_size_14 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / font_size_24 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / font_size_36 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / font_arial + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / font_times + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / font_courier + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / color_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / read / combined + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pylightxl / write / bold + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / italic + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / underline_single + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / underline_double + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / strikethrough + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / bold_italic + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / font_size_8 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / font_size_14 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / font_size_24 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / font_size_36 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / font_arial + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / font_times + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / font_courier + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / color_red + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / color_blue + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / color_green + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / color_custom + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pylightxl / write / combined + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / read / bold + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pyexcel / read / italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pyexcel / read / underline_single + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pyexcel / read / underline_double + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pyexcel / read / strikethrough + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pyexcel / read / bold_italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pyexcel / read / font_size_8 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / font_size_14 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / font_size_24 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / font_size_36 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / font_arial + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / font_times + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / font_courier + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / color_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / read / combined + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pyexcel / write / bold + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / italic + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / underline_single + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / underline_double + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / strikethrough + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / bold_italic + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / font_size_8 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / font_size_14 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / font_size_24 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / font_size_36 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / font_arial + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / font_times + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / font_courier + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / color_red + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / color_blue + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / color_green + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / color_custom + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / pyexcel / write / combined + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## text_formatting / xlwt / write / color_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / xlwt / write / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / bold + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pandas / read / italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pandas / read / underline_single + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pandas / read / underline_double + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pandas / read / strikethrough + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pandas / read / bold_italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / pandas / read / font_size_8 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / font_size_14 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / font_size_24 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / font_size_36 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / font_arial + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / font_times + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / font_courier + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / color_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / read / combined + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / bold + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / italic + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / underline_single + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / underline_double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / strikethrough + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / bold_italic + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / font_size_8 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / font_size_14 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / font_size_24 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / font_size_36 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / font_arial + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / font_times + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / font_courier + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / color_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / pandas / write / combined + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / bold + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / openpyxl-readonly / read / italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / openpyxl-readonly / read / underline_single + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / openpyxl-readonly / read / underline_double + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / openpyxl-readonly / read / strikethrough + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / openpyxl-readonly / read / bold_italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / openpyxl-readonly / read / font_size_8 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / font_size_14 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / font_size_24 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / font_size_36 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / font_arial + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / font_times + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / font_courier + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / color_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / openpyxl-readonly / read / combined + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / bold + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / polars / read / italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / polars / read / underline_single + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / polars / read / underline_double + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / polars / read / strikethrough + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / polars / read / bold_italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / polars / read / font_size_8 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / font_size_14 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / font_size_24 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / font_size_36 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / font_arial + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / font_times + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / font_courier + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / color_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / polars / read / combined + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / bold + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / tablib / read / italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / tablib / read / underline_single + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / tablib / read / underline_double + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / tablib / read / strikethrough + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / tablib / read / bold_italic + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## text_formatting / tablib / read / font_size_8 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / font_size_14 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / font_size_24 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / font_size_36 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / font_arial + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / font_times + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / font_courier + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / color_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / read / combined + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / bold + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / italic + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / underline_single + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / underline_double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / strikethrough + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / bold_italic + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / font_size_8 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / font_size_14 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / font_size_24 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / font_size_36 + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / font_arial + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / font_times + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / font_courier + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / color_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## text_formatting / tablib / write / combined + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / python-calamine / read / bg_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / python-calamine / read / bg_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / python-calamine / read / bg_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / python-calamine / read / bg_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pylightxl / read / bg_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pylightxl / read / bg_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pylightxl / read / bg_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pylightxl / read / bg_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pylightxl / write / bg_red + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## background_colors / pylightxl / write / bg_blue + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## background_colors / pylightxl / write / bg_green + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## background_colors / pylightxl / write / bg_custom + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## background_colors / pyexcel / read / bg_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pyexcel / read / bg_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pyexcel / read / bg_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pyexcel / read / bg_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pyexcel / write / bg_red + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## background_colors / pyexcel / write / bg_blue + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## background_colors / pyexcel / write / bg_green + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## background_colors / pyexcel / write / bg_custom + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## background_colors / xlwt / write / bg_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / xlwt / write / bg_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pandas / read / bg_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pandas / read / bg_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pandas / read / bg_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pandas / read / bg_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pandas / write / bg_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pandas / write / bg_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pandas / write / bg_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / pandas / write / bg_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / openpyxl-readonly / read / bg_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / openpyxl-readonly / read / bg_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / openpyxl-readonly / read / bg_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / openpyxl-readonly / read / bg_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / polars / read / bg_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / polars / read / bg_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / polars / read / bg_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / polars / read / bg_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / tablib / read / bg_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / tablib / read / bg_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / tablib / read / bg_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / tablib / read / bg_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / tablib / write / bg_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / tablib / write / bg_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / tablib / write / bg_green + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## background_colors / tablib / write / bg_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / python-calamine / read / numfmt_currency + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / python-calamine / read / numfmt_percent + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / python-calamine / read / numfmt_date + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / python-calamine / read / numfmt_scientific + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / python-calamine / read / numfmt_custom_text + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pylightxl / read / numfmt_currency + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pylightxl / read / numfmt_percent + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pylightxl / read / numfmt_date + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pylightxl / read / numfmt_scientific + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pylightxl / read / numfmt_custom_text + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pylightxl / write / numfmt_currency + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## number_formats / pylightxl / write / numfmt_percent + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## number_formats / pylightxl / write / numfmt_date + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## number_formats / pylightxl / write / numfmt_scientific + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## number_formats / pylightxl / write / numfmt_custom_text + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## number_formats / pyexcel / read / numfmt_currency + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pyexcel / read / numfmt_percent + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pyexcel / read / numfmt_date + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pyexcel / read / numfmt_scientific + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pyexcel / read / numfmt_custom_text + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pyexcel / write / numfmt_currency + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## number_formats / pyexcel / write / numfmt_percent + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## number_formats / pyexcel / write / numfmt_date + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## number_formats / pyexcel / write / numfmt_scientific + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## number_formats / pyexcel / write / numfmt_custom_text + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## number_formats / pandas / read / numfmt_currency + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pandas / read / numfmt_percent + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pandas / read / numfmt_date + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pandas / read / numfmt_scientific + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pandas / read / numfmt_custom_text + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pandas / write / numfmt_currency + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pandas / write / numfmt_percent + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pandas / write / numfmt_date + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pandas / write / numfmt_scientific + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / pandas / write / numfmt_custom_text + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / openpyxl-readonly / read / numfmt_currency + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / openpyxl-readonly / read / numfmt_percent + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / openpyxl-readonly / read / numfmt_date + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / openpyxl-readonly / read / numfmt_scientific + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / openpyxl-readonly / read / numfmt_custom_text + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / polars / read / numfmt_currency + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / polars / read / numfmt_percent + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / polars / read / numfmt_date + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / polars / read / numfmt_scientific + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / polars / read / numfmt_custom_text + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / tablib / read / numfmt_currency + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / tablib / read / numfmt_percent + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / tablib / read / numfmt_date + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / tablib / read / numfmt_scientific + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / tablib / read / numfmt_custom_text + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / tablib / write / numfmt_currency + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / tablib / write / numfmt_percent + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / tablib / write / numfmt_date + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / tablib / write / numfmt_scientific + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## number_formats / tablib / write / numfmt_custom_text + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## alignment / xlsxwriter / write / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / python-calamine / read / h_left + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / python-calamine / read / h_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / python-calamine / read / h_right + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / python-calamine / read / v_top + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / python-calamine / read / v_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / python-calamine / read / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / python-calamine / read / wrap_text + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / python-calamine / read / rotation_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / python-calamine / read / indent_2 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / aspose-cells-foss / read / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / aspose-cells-foss / write / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pylightxl / read / h_left + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## alignment / pylightxl / read / h_center + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## alignment / pylightxl / read / h_right + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## alignment / pylightxl / read / v_top + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## alignment / pylightxl / read / v_center + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## alignment / pylightxl / read / v_bottom + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## alignment / pylightxl / read / wrap_text + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## alignment / pylightxl / read / rotation_45 + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## alignment / pylightxl / read / indent_2 + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## alignment / pylightxl / write / h_left + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pylightxl / write / h_center + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pylightxl / write / h_right + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pylightxl / write / v_top + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pylightxl / write / v_center + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pylightxl / write / v_bottom + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pylightxl / write / wrap_text + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pylightxl / write / rotation_45 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pylightxl / write / indent_2 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pyexcel / read / h_left + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pyexcel / read / h_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pyexcel / read / h_right + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pyexcel / read / v_top + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pyexcel / read / v_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pyexcel / read / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pyexcel / read / wrap_text + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pyexcel / read / rotation_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pyexcel / read / indent_2 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pyexcel / write / h_left + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pyexcel / write / h_center + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pyexcel / write / h_right + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pyexcel / write / v_top + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pyexcel / write / v_center + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pyexcel / write / v_bottom + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pyexcel / write / wrap_text + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pyexcel / write / rotation_45 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pyexcel / write / indent_2 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## alignment / pandas / read / h_left + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / read / h_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / read / h_right + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / read / v_top + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / read / v_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / read / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / read / wrap_text + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / read / rotation_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / read / indent_2 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / write / h_left + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / write / h_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / write / h_right + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / write / v_top + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / write / v_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / write / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / write / wrap_text + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / write / rotation_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / pandas / write / indent_2 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / xlsxwriter-constmem / write / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / openpyxl-readonly / read / h_left + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / openpyxl-readonly / read / h_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / openpyxl-readonly / read / h_right + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / openpyxl-readonly / read / v_top + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / openpyxl-readonly / read / v_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / openpyxl-readonly / read / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / openpyxl-readonly / read / wrap_text + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / openpyxl-readonly / read / rotation_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / openpyxl-readonly / read / indent_2 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / polars / read / h_left + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / polars / read / h_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / polars / read / h_right + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / polars / read / v_top + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / polars / read / v_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / polars / read / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / polars / read / wrap_text + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / polars / read / rotation_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / polars / read / indent_2 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / read / h_left + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / read / h_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / read / h_right + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / read / v_top + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / read / v_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / read / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / read / wrap_text + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / read / rotation_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / read / indent_2 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / write / h_left + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / write / h_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / write / h_right + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / write / v_top + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / write / v_center + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / write / v_bottom + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / write / wrap_text + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / write / rotation_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## alignment / tablib / write / indent_2 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / python-calamine / read / thin_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / medium_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / thick_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / dashed + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / dotted + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / dash_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / dash_dot_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / top_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / python-calamine / read / bottom_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / python-calamine / read / left_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / python-calamine / read / right_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / python-calamine / read / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / python-calamine / read / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / python-calamine / read / diagonal_both + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / python-calamine / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / python-calamine / read / mixed_styles + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / python-calamine / read / mixed_colors + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / aspose-cells-foss / read / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / aspose-cells-foss / read / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / aspose-cells-foss / read / diagonal_both + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / aspose-cells-foss / write / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / aspose-cells-foss / write / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / aspose-cells-foss / write / diagonal_both + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pylightxl / read / thin_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / medium_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / thick_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / dashed + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / dotted + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / dash_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / dash_dot_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / top_only + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## borders / pylightxl / read / bottom_only + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## borders / pylightxl / read / left_only + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## borders / pylightxl / read / right_only + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## borders / pylightxl / read / diagonal_up + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## borders / pylightxl / read / diagonal_down + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## borders / pylightxl / read / diagonal_both + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## borders / pylightxl / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / read / mixed_styles + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## borders / pylightxl / read / mixed_colors + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pylightxl / write / thin_all + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / medium_all + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / thick_all + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / double + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / dashed + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / dotted + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / dash_dot + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / dash_dot_dot + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / top_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / bottom_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / left_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / right_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / diagonal_up + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / diagonal_down + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / diagonal_both + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / color_red + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / color_blue + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / color_custom + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / mixed_styles + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pylightxl / write / mixed_colors + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / read / thin_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / medium_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / thick_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / dashed + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / dotted + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / dash_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / dash_dot_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / top_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pyexcel / read / bottom_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pyexcel / read / left_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pyexcel / read / right_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pyexcel / read / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pyexcel / read / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pyexcel / read / diagonal_both + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pyexcel / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / read / mixed_styles + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pyexcel / read / mixed_colors + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pyexcel / write / thin_all + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / medium_all + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / thick_all + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / double + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / dashed + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / dotted + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / dash_dot + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / dash_dot_dot + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / top_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / bottom_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / left_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / right_only + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / diagonal_up + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / diagonal_down + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / diagonal_both + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / color_red + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / color_blue + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / color_custom + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / mixed_styles + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / pyexcel / write / mixed_colors + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel exposes value-only cells +- Next debug surface: treat as unsupported capability, not a semantic regression + +## borders / xlwt / write / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / xlwt / write / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / xlwt / write / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / xlwt / write / mixed_colors + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / thin_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / medium_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / thick_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / dashed + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / dotted + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / dash_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / dash_dot_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / top_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / read / bottom_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / read / left_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / read / right_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / read / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / read / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / read / diagonal_both + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / read / mixed_styles + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / read / mixed_colors + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / thin_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / medium_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / thick_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / dashed + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / dotted + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / dash_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / dash_dot_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / top_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / write / bottom_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / write / left_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / write / right_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / write / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / write / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / write / diagonal_both + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / write / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / pandas / write / mixed_styles + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / pandas / write / mixed_colors + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / thin_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / medium_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / thick_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / dashed + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / dotted + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / dash_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / dash_dot_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / top_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / openpyxl-readonly / read / bottom_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / openpyxl-readonly / read / left_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / openpyxl-readonly / read / right_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / openpyxl-readonly / read / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / openpyxl-readonly / read / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / openpyxl-readonly / read / diagonal_both + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / openpyxl-readonly / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / openpyxl-readonly / read / mixed_styles + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / openpyxl-readonly / read / mixed_colors + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / thin_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / medium_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / thick_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / dashed + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / dotted + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / dash_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / dash_dot_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / top_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / polars / read / bottom_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / polars / read / left_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / polars / read / right_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / polars / read / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / polars / read / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / polars / read / diagonal_both + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / polars / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / polars / read / mixed_styles + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / polars / read / mixed_colors + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / thin_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / medium_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / thick_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / dashed + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / dotted + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / dash_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / dash_dot_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / top_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / read / bottom_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / read / left_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / read / right_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / read / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / read / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / read / diagonal_both + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / read / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / read / mixed_styles + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / read / mixed_colors + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / thin_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / medium_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / thick_all + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / double + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / dashed + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / dotted + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / dash_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / dash_dot_dot + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / top_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / write / bottom_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / write / left_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / write / right_only + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / write / diagonal_up + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / write / diagonal_down + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / write / diagonal_both + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / write / color_red + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / color_blue + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / color_custom + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## borders / tablib / write / mixed_styles + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## borders / tablib / write / mixed_colors + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## dimensions / python-calamine / read / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / python-calamine / read / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / python-calamine / read / col_width_20 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / python-calamine / read / col_width_8 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / aspose-cells-foss / read / col_width_20 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / aspose-cells-foss / read / col_width_8 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pylightxl / read / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pylightxl / read / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pylightxl / read / col_width_20 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pylightxl / read / col_width_8 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pylightxl / write / row_height_30 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## dimensions / pylightxl / write / row_height_45 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## dimensions / pylightxl / write / col_width_20 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## dimensions / pylightxl / write / col_width_8 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## dimensions / pyexcel / read / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pyexcel / read / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pyexcel / read / col_width_20 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pyexcel / read / col_width_8 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pyexcel / write / row_height_30 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose row dimension writing +- Next debug surface: treat as unsupported capability, not a semantic regression + +## dimensions / pyexcel / write / row_height_45 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose row dimension writing +- Next debug surface: treat as unsupported capability, not a semantic regression + +## dimensions / pyexcel / write / col_width_20 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose row dimension writing +- Next debug surface: treat as unsupported capability, not a semantic regression + +## dimensions / pyexcel / write / col_width_8 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose row dimension writing +- Next debug surface: treat as unsupported capability, not a semantic regression + +## dimensions / xlwt / write / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / xlwt / write / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pandas / read / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pandas / read / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pandas / read / col_width_20 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pandas / read / col_width_8 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pandas / write / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pandas / write / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pandas / write / col_width_20 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / pandas / write / col_width_8 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / xlsxwriter-constmem / write / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / xlsxwriter-constmem / write / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / openpyxl-readonly / read / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / openpyxl-readonly / read / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / openpyxl-readonly / read / col_width_20 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / openpyxl-readonly / read / col_width_8 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / polars / read / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / polars / read / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / polars / read / col_width_20 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / polars / read / col_width_8 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / tablib / read / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / tablib / read / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / tablib / read / col_width_20 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / tablib / read / col_width_8 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / tablib / write / row_height_30 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / tablib / write / row_height_45 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / tablib / write / col_width_20 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## dimensions / tablib / write / col_width_8 + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## multiple_sheets / polars / read / value_beta + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## multiple_sheets / polars / read / value_gamma + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## merged_cells / python-calamine / read / merge_horizontal + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / python-calamine / read / merge_vertical + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / python-calamine / read / merge_value_off_top_left + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / python-calamine / read / merge_top_left_fill + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## merged_cells / pylightxl / read / merge_horizontal + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pylightxl / read / merge_vertical + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pylightxl / read / merge_value_off_top_left + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pylightxl / read / merge_top_left_fill + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## merged_cells / pylightxl / write / merge_horizontal + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## merged_cells / pylightxl / write / merge_vertical + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## merged_cells / pylightxl / write / merge_value_off_top_left + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## merged_cells / pylightxl / write / merge_top_left_fill + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## merged_cells / pyexcel / read / merge_horizontal + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pyexcel / read / merge_vertical + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pyexcel / read / merge_value_off_top_left + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pyexcel / read / merge_top_left_fill + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## merged_cells / pyexcel / write / merge_horizontal + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## merged_cells / pyexcel / write / merge_vertical + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## merged_cells / pyexcel / write / merge_value_off_top_left + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## merged_cells / pyexcel / write / merge_top_left_fill + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## merged_cells / xlwt / write / merge_horizontal + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / xlwt / write / merge_vertical + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / xlwt / write / merge_value_off_top_left + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / xlwt / write / merge_top_left_fill + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## merged_cells / pandas / read / merge_horizontal + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pandas / read / merge_vertical + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pandas / read / merge_value_off_top_left + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pandas / read / merge_top_left_fill + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## merged_cells / pandas / write / merge_horizontal + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pandas / write / merge_vertical + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pandas / write / merge_value_off_top_left + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / pandas / write / merge_top_left_fill + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## merged_cells / openpyxl-readonly / read / merge_horizontal + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / openpyxl-readonly / read / merge_vertical + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / openpyxl-readonly / read / merge_value_off_top_left + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / openpyxl-readonly / read / merge_top_left_fill + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## merged_cells / polars / read / merge_horizontal + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / polars / read / merge_vertical + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / polars / read / merge_value_off_top_left + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / polars / read / merge_top_left_fill + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## merged_cells / tablib / read / merge_horizontal + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / tablib / read / merge_vertical + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / tablib / read / merge_value_off_top_left + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / tablib / read / merge_top_left_fill + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## merged_cells / tablib / write / merge_horizontal + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / tablib / write / merge_vertical + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / tablib / write / merge_value_off_top_left + +- What failed: merged-cell metadata changed +- Likely cause: merged range XML or non-anchor cell handling differs +- Next debug surface: inspect mergeCells in the worksheet XML and subordinate cell behavior + +## merged_cells / tablib / write / merge_top_left_fill + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / python-calamine / read / cf_cell_gt + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / python-calamine / read / cf_formula_cross_sheet + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / python-calamine / read / cf_text_contains + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / python-calamine / read / cf_data_bar + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## conditional_formatting / python-calamine / read / cf_color_scale + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / python-calamine / read / cf_stop_if_true + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / wolfxl / read / cf_cell_gt + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / wolfxl / read / cf_formula_cross_sheet + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / wolfxl / read / cf_text_contains + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / wolfxl / read / cf_stop_if_true + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pylightxl / read / cf_cell_gt + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pylightxl / read / cf_formula_cross_sheet + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pylightxl / read / cf_text_contains + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pylightxl / read / cf_data_bar + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## conditional_formatting / pylightxl / read / cf_color_scale + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pylightxl / read / cf_stop_if_true + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pylightxl / write / cf_cell_gt + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pylightxl / write / cf_formula_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pylightxl / write / cf_text_contains + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pylightxl / write / cf_data_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pylightxl / write / cf_color_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pylightxl / write / cf_stop_if_true + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pyexcel / read / cf_cell_gt + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pyexcel / read / cf_formula_cross_sheet + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pyexcel / read / cf_text_contains + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pyexcel / read / cf_data_bar + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## conditional_formatting / pyexcel / read / cf_color_scale + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pyexcel / read / cf_stop_if_true + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pyexcel / write / cf_cell_gt + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pyexcel / write / cf_formula_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pyexcel / write / cf_text_contains + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pyexcel / write / cf_data_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pyexcel / write / cf_color_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pyexcel / write / cf_stop_if_true + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / xlwt / write / cf_cell_gt + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author conditional formatting +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / xlwt / write / cf_formula_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author conditional formatting +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / xlwt / write / cf_text_contains + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author conditional formatting +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / xlwt / write / cf_data_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author conditional formatting +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / xlwt / write / cf_color_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author conditional formatting +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / xlwt / write / cf_stop_if_true + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author conditional formatting +- Next debug surface: treat as unsupported capability, not a semantic regression + +## conditional_formatting / pandas / read / cf_cell_gt + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pandas / read / cf_formula_cross_sheet + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pandas / read / cf_text_contains + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pandas / read / cf_data_bar + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## conditional_formatting / pandas / read / cf_color_scale + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pandas / read / cf_stop_if_true + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pandas / write / cf_cell_gt + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pandas / write / cf_formula_cross_sheet + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pandas / write / cf_text_contains + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pandas / write / cf_data_bar + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## conditional_formatting / pandas / write / cf_color_scale + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / pandas / write / cf_stop_if_true + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / openpyxl-readonly / read / cf_cell_gt + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / openpyxl-readonly / read / cf_formula_cross_sheet + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / openpyxl-readonly / read / cf_text_contains + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / openpyxl-readonly / read / cf_data_bar + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## conditional_formatting / openpyxl-readonly / read / cf_color_scale + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / openpyxl-readonly / read / cf_stop_if_true + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / polars / read / cf_cell_gt + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / polars / read / cf_formula_cross_sheet + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / polars / read / cf_text_contains + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / polars / read / cf_data_bar + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## conditional_formatting / polars / read / cf_color_scale + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / polars / read / cf_stop_if_true + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / tablib / read / cf_cell_gt + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / tablib / read / cf_formula_cross_sheet + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / tablib / read / cf_text_contains + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / tablib / read / cf_data_bar + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## conditional_formatting / tablib / read / cf_color_scale + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / tablib / read / cf_stop_if_true + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / tablib / write / cf_cell_gt + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / tablib / write / cf_formula_cross_sheet + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / tablib / write / cf_text_contains + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / tablib / write / cf_data_bar + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## conditional_formatting / tablib / write / cf_color_scale + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## conditional_formatting / tablib / write / cf_stop_if_true + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## data_validation / python-calamine / read / dv_list_csv + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / python-calamine / read / dv_list_range + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / python-calamine / read / dv_cross_sheet + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / python-calamine / read / dv_custom_formula + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / python-calamine / read / dv_whole_between + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pylightxl / read / dv_list_csv + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pylightxl / read / dv_list_range + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pylightxl / read / dv_cross_sheet + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pylightxl / read / dv_custom_formula + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pylightxl / read / dv_whole_between + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pylightxl / write / dv_list_csv + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / pylightxl / write / dv_list_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / pylightxl / write / dv_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / pylightxl / write / dv_custom_formula + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / pylightxl / write / dv_whole_between + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / pyexcel / read / dv_list_csv + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pyexcel / read / dv_list_range + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pyexcel / read / dv_cross_sheet + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pyexcel / read / dv_custom_formula + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pyexcel / read / dv_whole_between + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pyexcel / write / dv_list_csv + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / pyexcel / write / dv_list_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / pyexcel / write / dv_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / pyexcel / write / dv_custom_formula + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / pyexcel / write / dv_whole_between + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / xlwt / write / dv_list_csv + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author data validations +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / xlwt / write / dv_list_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author data validations +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / xlwt / write / dv_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author data validations +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / xlwt / write / dv_custom_formula + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author data validations +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / xlwt / write / dv_whole_between + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author data validations +- Next debug surface: treat as unsupported capability, not a semantic regression + +## data_validation / pandas / read / dv_list_csv + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pandas / read / dv_list_range + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pandas / read / dv_cross_sheet + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pandas / read / dv_custom_formula + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pandas / read / dv_whole_between + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pandas / write / dv_list_csv + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pandas / write / dv_list_range + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pandas / write / dv_cross_sheet + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pandas / write / dv_custom_formula + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / pandas / write / dv_whole_between + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / openpyxl-readonly / read / dv_list_csv + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / openpyxl-readonly / read / dv_list_range + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / openpyxl-readonly / read / dv_cross_sheet + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / openpyxl-readonly / read / dv_custom_formula + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / openpyxl-readonly / read / dv_whole_between + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / polars / read / dv_list_csv + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / polars / read / dv_list_range + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / polars / read / dv_cross_sheet + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / polars / read / dv_custom_formula + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / polars / read / dv_whole_between + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / tablib / read / dv_list_csv + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / tablib / read / dv_list_range + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / tablib / read / dv_cross_sheet + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / tablib / read / dv_custom_formula + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / tablib / read / dv_whole_between + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / tablib / write / dv_list_csv + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / tablib / write / dv_list_range + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / tablib / write / dv_cross_sheet + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / tablib / write / dv_custom_formula + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## data_validation / tablib / write / dv_whole_between + +- What failed: data validation metadata changed +- Likely cause: validation type, formula, or target range was dropped or rewritten +- Next debug surface: inspect dataValidations in the worksheet XML + +## hyperlinks / python-calamine / read / link_external + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / python-calamine / read / link_internal + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / python-calamine / read / link_mailto + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / python-calamine / read / link_long + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / aspose-cells-foss / read / link_external + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / aspose-cells-foss / read / link_internal + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / aspose-cells-foss / read / link_mailto + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / aspose-cells-foss / read / link_long + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pylightxl / read / link_external + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pylightxl / read / link_internal + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pylightxl / read / link_mailto + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pylightxl / read / link_long + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pylightxl / write / link_external + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / pylightxl / write / link_internal + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / pylightxl / write / link_mailto + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / pylightxl / write / link_long + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / pyexcel / read / link_external + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pyexcel / read / link_internal + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pyexcel / read / link_mailto + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pyexcel / read / link_long + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pyexcel / write / link_external + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / pyexcel / write / link_internal + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / pyexcel / write / link_mailto + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / pyexcel / write / link_long + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / xlwt / write / link_external + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt hyperlink metadata is not supported in this adapter +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / xlwt / write / link_internal + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt hyperlink metadata is not supported in this adapter +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / xlwt / write / link_mailto + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt hyperlink metadata is not supported in this adapter +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / xlwt / write / link_long + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt hyperlink metadata is not supported in this adapter +- Next debug surface: treat as unsupported capability, not a semantic regression + +## hyperlinks / pandas / read / link_external + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pandas / read / link_internal + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pandas / read / link_mailto + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pandas / read / link_long + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pandas / write / link_external + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pandas / write / link_internal + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pandas / write / link_mailto + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / pandas / write / link_long + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / openpyxl-readonly / read / link_external + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / openpyxl-readonly / read / link_internal + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / openpyxl-readonly / read / link_mailto + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / openpyxl-readonly / read / link_long + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / polars / read / link_external + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / polars / read / link_internal + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / polars / read / link_mailto + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / polars / read / link_long + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / tablib / read / link_external + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / tablib / read / link_internal + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / tablib / read / link_mailto + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / tablib / read / link_long + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / tablib / write / link_external + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / tablib / write / link_internal + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / tablib / write / link_mailto + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## hyperlinks / tablib / write / link_long + +- What failed: hyperlink target or display metadata changed +- Likely cause: hyperlink rel target, tooltip, or internal location was not preserved +- Next debug surface: inspect worksheet hyperlinks and worksheet rels + +## images / python-calamine / read / image_one_cell + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / python-calamine / read / image_two_cell_offset + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / aspose-cells-foss / read / image_one_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / aspose-cells-foss / read / image_two_cell_offset + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / aspose-cells-foss / write / image_one_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / aspose-cells-foss / write / image_two_cell_offset + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / pylightxl / read / image_one_cell + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / pylightxl / read / image_two_cell_offset + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / pylightxl / write / image_one_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / pylightxl / write / image_two_cell_offset + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / pyexcel / read / image_one_cell + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / pyexcel / read / image_two_cell_offset + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / pyexcel / write / image_one_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / pyexcel / write / image_two_cell_offset + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / xlwt / write / image_one_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot embed images in this adapter +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / xlwt / write / image_two_cell_offset + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot embed images in this adapter +- Next debug surface: treat as unsupported capability, not a semantic regression + +## images / pandas / read / image_one_cell + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / pandas / read / image_two_cell_offset + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / pandas / write / image_one_cell + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / pandas / write / image_two_cell_offset + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / xlsxwriter-constmem / write / image_one_cell + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / xlsxwriter-constmem / write / image_two_cell_offset + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / openpyxl-readonly / read / image_one_cell + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / openpyxl-readonly / read / image_two_cell_offset + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / polars / read / image_one_cell + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / polars / read / image_two_cell_offset + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / tablib / read / image_one_cell + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / tablib / read / image_two_cell_offset + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / tablib / write / image_one_cell + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## images / tablib / write / image_two_cell_offset + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## comments / python-calamine / read / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / python-calamine / read / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / python-calamine / read / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / aspose-cells-foss / write / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / aspose-cells-foss / write / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / aspose-cells-foss / write / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pylightxl / read / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pylightxl / read / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pylightxl / read / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pylightxl / write / comment_legacy + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## comments / pylightxl / write / comment_threaded + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## comments / pylightxl / write / comment_author + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## comments / pyexcel / read / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pyexcel / read / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pyexcel / read / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pyexcel / write / comment_legacy + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## comments / pyexcel / write / comment_threaded + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## comments / pyexcel / write / comment_author + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## comments / xlwt / write / comment_legacy + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author comments +- Next debug surface: treat as unsupported capability, not a semantic regression + +## comments / xlwt / write / comment_threaded + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author comments +- Next debug surface: treat as unsupported capability, not a semantic regression + +## comments / xlwt / write / comment_author + +- What failed: adapter reported this operation as unsupported +- Likely cause: xlwt cannot author comments +- Next debug surface: treat as unsupported capability, not a semantic regression + +## comments / pandas / read / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pandas / read / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pandas / read / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pandas / write / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pandas / write / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / pandas / write / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / xlsxwriter-constmem / write / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / xlsxwriter-constmem / write / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / xlsxwriter-constmem / write / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / openpyxl-readonly / read / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / openpyxl-readonly / read / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / openpyxl-readonly / read / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / polars / read / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / polars / read / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / polars / read / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / tablib / read / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / tablib / read / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / tablib / read / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / tablib / write / comment_legacy + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / tablib / write / comment_threaded + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## comments / tablib / write / comment_author + +- What failed: comment metadata changed +- Likely cause: legacy comment text, author, or VML relationship was not preserved +- Next debug surface: inspect comments XML plus VML drawing relationships + +## freeze_panes / python-calamine / read / freeze_b2 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / python-calamine / read / freeze_d5 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / python-calamine / read / split_2x1 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pylightxl / read / freeze_b2 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pylightxl / read / freeze_d5 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pylightxl / read / split_2x1 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pylightxl / write / freeze_b2 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## freeze_panes / pylightxl / write / freeze_d5 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## freeze_panes / pylightxl / write / split_2x1 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pylightxl does not implement this feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## freeze_panes / pyexcel / read / freeze_b2 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pyexcel / read / freeze_d5 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pyexcel / read / split_2x1 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pyexcel / write / freeze_b2 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## freeze_panes / pyexcel / write / freeze_d5 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## freeze_panes / pyexcel / write / split_2x1 + +- What failed: adapter reported this operation as unsupported +- Likely cause: pyexcel does not expose this worksheet feature +- Next debug surface: treat as unsupported capability, not a semantic regression + +## freeze_panes / xlwt / write / freeze_b2 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / xlwt / write / freeze_d5 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / xlwt / write / split_2x1 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pandas / read / freeze_b2 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pandas / read / freeze_d5 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pandas / read / split_2x1 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pandas / write / freeze_b2 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pandas / write / freeze_d5 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / pandas / write / split_2x1 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / openpyxl-readonly / read / freeze_b2 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / openpyxl-readonly / read / freeze_d5 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / openpyxl-readonly / read / split_2x1 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / polars / read / freeze_b2 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / polars / read / freeze_d5 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / polars / read / split_2x1 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / tablib / read / freeze_b2 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / tablib / read / freeze_d5 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / tablib / read / split_2x1 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / tablib / write / freeze_b2 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / tablib / write / freeze_d5 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## freeze_panes / tablib / write / split_2x1 + +- What failed: freeze pane settings changed +- Likely cause: pane split/top-left metadata was dropped or normalized incorrectly +- Next debug surface: inspect sheetViews/pane in the worksheet XML + +## named_ranges / xlsxwriter / write / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter / write / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter / write / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter / write / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter / write / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter / write / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / python-calamine / read / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / python-calamine / read / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / python-calamine / read / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / python-calamine / read / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / python-calamine / read / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / python-calamine / read / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / aspose-cells-foss / read / nr_sheet_scope + +- What failed: named range metadata changed +- Likely cause: workbook-level vs sheet-level defined-name scope was lost or rewritten +- Next debug surface: inspect workbook.xml definedNames and localSheetId values + +## named_ranges / wolfxl / write / nr_sheet_scope + +- What failed: named range metadata changed +- Likely cause: workbook-level vs sheet-level defined-name scope was lost or rewritten +- Next debug surface: inspect workbook.xml definedNames and localSheetId values + +## named_ranges / pylightxl / read / nr_simple_cell + +- What failed: named range metadata changed +- Likely cause: workbook-level vs sheet-level defined-name scope was lost or rewritten +- Next debug surface: inspect workbook.xml definedNames and localSheetId values + +## named_ranges / pylightxl / read / nr_cell_range + +- What failed: named range metadata changed +- Likely cause: workbook-level vs sheet-level defined-name scope was lost or rewritten +- Next debug surface: inspect workbook.xml definedNames and localSheetId values + +## named_ranges / pylightxl / read / nr_formula_ref + +- What failed: named range metadata changed +- Likely cause: workbook-level vs sheet-level defined-name scope was lost or rewritten +- Next debug surface: inspect workbook.xml definedNames and localSheetId values + +## named_ranges / pylightxl / read / nr_sheet_scope + +- What failed: named range metadata changed +- Likely cause: workbook-level vs sheet-level defined-name scope was lost or rewritten +- Next debug surface: inspect workbook.xml definedNames and localSheetId values + +## named_ranges / pylightxl / read / nr_cross_sheet + +- What failed: named range metadata changed +- Likely cause: workbook-level vs sheet-level defined-name scope was lost or rewritten +- Next debug surface: inspect workbook.xml definedNames and localSheetId values + +## named_ranges / pylightxl / read / nr_special_chars + +- What failed: named range metadata changed +- Likely cause: workbook-level vs sheet-level defined-name scope was lost or rewritten +- Next debug surface: inspect workbook.xml definedNames and localSheetId values + +## named_ranges / pylightxl / write / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pylightxl / write / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pylightxl / write / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pylightxl / write / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pylightxl / write / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pylightxl / write / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / read / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / read / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / read / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / read / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / read / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / read / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / write / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / write / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / write / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / write / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / write / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pyexcel / write / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlwt / write / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlwt / write / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlwt / write / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlwt / write / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlwt / write / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlwt / write / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / read / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / read / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / read / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / read / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / read / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / read / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / write / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / write / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / write / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / write / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / write / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / pandas / write / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter-constmem / write / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter-constmem / write / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter-constmem / write / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter-constmem / write / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter-constmem / write / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / xlsxwriter-constmem / write / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / openpyxl-readonly / read / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / openpyxl-readonly / read / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / openpyxl-readonly / read / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / openpyxl-readonly / read / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / openpyxl-readonly / read / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / openpyxl-readonly / read / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / polars / read / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / polars / read / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / polars / read / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / polars / read / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / polars / read / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / polars / read / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / read / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / read / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / read / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / read / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / read / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / read / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / write / nr_simple_cell + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / write / nr_cell_range + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / write / nr_formula_ref + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / write / nr_sheet_scope + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / write / nr_cross_sheet + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## named_ranges / tablib / write / nr_special_chars + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter / write / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter / write / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter / write / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter / write / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter / write / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter / write / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / python-calamine / read / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / python-calamine / read / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / python-calamine / read / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / python-calamine / read / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / python-calamine / read / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / python-calamine / read / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / aspose-cells-foss / read / tbl_with_totals + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## tables / aspose-cells-foss / read / tbl_no_style + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## tables / aspose-cells-foss / write / tbl_with_totals + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## tables / aspose-cells-foss / write / tbl_no_style + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## tables / pylightxl / read / tbl_basic + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## tables / pylightxl / read / tbl_with_totals + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## tables / pylightxl / read / tbl_no_style + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## tables / pylightxl / read / tbl_single_col + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## tables / pylightxl / read / tbl_single_row + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## tables / pylightxl / read / tbl_autofilter + +- What failed: cell style metadata changed +- Likely cause: formatting was dropped, defaulted, or normalized differently +- Next debug surface: inspect styles.xml and the adapter's style mapping + +## tables / pylightxl / write / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pylightxl / write / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pylightxl / write / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pylightxl / write / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pylightxl / write / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pylightxl / write / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / read / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / read / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / read / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / read / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / read / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / read / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / write / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / write / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / write / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / write / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / write / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pyexcel / write / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlwt / write / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlwt / write / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlwt / write / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlwt / write / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlwt / write / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlwt / write / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / read / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / read / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / read / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / read / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / read / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / read / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / write / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / write / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / write / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / write / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / write / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / pandas / write / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter-constmem / write / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter-constmem / write / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter-constmem / write / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter-constmem / write / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter-constmem / write / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / xlsxwriter-constmem / write / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / openpyxl-readonly / read / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / openpyxl-readonly / read / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / openpyxl-readonly / read / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / openpyxl-readonly / read / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / openpyxl-readonly / read / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / openpyxl-readonly / read / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / polars / read / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / polars / read / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / polars / read / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / polars / read / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / polars / read / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / polars / read / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / read / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / read / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / read / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / read / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / read / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / read / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / write / tbl_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / write / tbl_with_totals + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / write / tbl_no_style + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / write / tbl_single_col + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / write / tbl_single_row + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## tables / tablib / write / tbl_autofilter + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / xlsxwriter / write / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / xlsxwriter / write / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / xlsxwriter / write / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / python-calamine / read / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / python-calamine / read / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / python-calamine / read / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pylightxl / read / prot_basic + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## sheet_protection / pylightxl / read / prot_password + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## sheet_protection / pylightxl / read / prot_granular + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## sheet_protection / pylightxl / write / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pylightxl / write / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pylightxl / write / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pyexcel / read / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pyexcel / read / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pyexcel / read / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pyexcel / write / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pyexcel / write / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pyexcel / write / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / xlwt / write / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / xlwt / write / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / xlwt / write / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pandas / read / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pandas / read / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pandas / read / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pandas / write / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pandas / write / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / pandas / write / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / xlsxwriter-constmem / write / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / xlsxwriter-constmem / write / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / xlsxwriter-constmem / write / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / openpyxl-readonly / read / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / openpyxl-readonly / read / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / openpyxl-readonly / read / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / polars / read / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / polars / read / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / polars / read / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / tablib / read / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / tablib / read / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / tablib / read / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / tablib / write / prot_basic + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / tablib / write / prot_password + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## sheet_protection / tablib / write / prot_granular + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / xlsxwriter / write / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / xlsxwriter / write / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / xlsxwriter / write / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / python-calamine / read / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / python-calamine / read / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / python-calamine / read / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / aspose-cells-foss / read / page_setup_landscape + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## page_setup / aspose-cells-foss / read / page_setup_titles + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## page_setup / aspose-cells-foss / write / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss has no print-title-rows API. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / aspose-cells-foss / write / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss has no print-title-rows API. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / aspose-cells-foss / write / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: aspose-cells-foss has no print-title-rows API. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / wolfxl / write / page_setup_titles + +- What failed: benchmark expectation did not match actual output. +- Likely cause: no known failure archetype matched this payload. +- Next debug surface: inspect expected/actual payloads in results.json. + +## page_setup / pylightxl / read / page_setup_landscape + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## page_setup / pylightxl / read / page_setup_scale + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## page_setup / pylightxl / read / page_setup_titles + +- What failed: adapter raised instead of returning comparable workbook data +- Likely cause: adapter/runtime error interrupted the assertion path +- Next debug surface: open the diagnostic adapter message and reproduce the adapter call directly + +## page_setup / pylightxl / write / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pylightxl / write / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pylightxl / write / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pyexcel / read / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pyexcel / read / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pyexcel / read / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pyexcel / write / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pyexcel / write / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pyexcel / write / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / xlwt / write / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / xlwt / write / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / xlwt / write / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pandas / read / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pandas / read / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pandas / read / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pandas / write / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pandas / write / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / pandas / write / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / xlsxwriter-constmem / write / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / xlsxwriter-constmem / write / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / xlsxwriter-constmem / write / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / openpyxl-readonly / read / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / openpyxl-readonly / read / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / openpyxl-readonly / read / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / polars / read / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / polars / read / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / polars / read / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / tablib / read / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / tablib / read / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / tablib / read / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / tablib / write / page_setup_landscape + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / tablib / write / page_setup_scale + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## page_setup / tablib / write / page_setup_titles + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / xlsxwriter / write / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / xlsxwriter / write / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / python-calamine / read / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / python-calamine / read / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / pylightxl / read / chart_bar + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## chart_anchor / pylightxl / read / chart_line + +- What failed: image or drawing relationship changed +- Likely cause: media part may exist but worksheet drawing rels or anchors do not match +- Next debug surface: inspect drawing XML, drawing rels, and xl/media package parts + +## chart_anchor / pylightxl / write / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / pylightxl / write / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / pyexcel / read / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / pyexcel / read / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / pyexcel / write / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / pyexcel / write / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / xlwt / write / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / xlwt / write / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / pandas / read / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / pandas / read / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / pandas / write / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / pandas / write / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / xlsxwriter-constmem / write / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / xlsxwriter-constmem / write / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / openpyxl-readonly / read / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / openpyxl-readonly / read / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / polars / read / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / polars / read / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / tablib / read / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / tablib / read / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter raised an exception while evaluating this test case. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / tablib / write / chart_bar + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression + +## chart_anchor / tablib / write / chart_line + +- What failed: adapter reported this operation as unsupported +- Likely cause: Adapter could not create or save a workbook for this feature. +- Next debug surface: treat as unsupported capability, not a semantic regression diff --git a/results-2026-09-08/xlsx/history.jsonl b/results-2026-09-08/xlsx/history.jsonl new file mode 100644 index 0000000..a5ab36c --- /dev/null +++ b/results-2026-09-08/xlsx/history.jsonl @@ -0,0 +1 @@ +{"run_date": "2026-09-08T05:35:34.204256+00:00", "commit": "9a0b300", "profile": "xlsx", "scores": {"openpyxl": {"cell_values": {"read": 3, "write": 3}, "formulas": {"read": 3, "write": 3}, "text_formatting": {"read": 3, "write": 3}, "background_colors": {"read": 3, "write": 3}, "number_formats": {"read": 3, "write": 3}, "alignment": {"read": 3, "write": 3}, "borders": {"read": 3, "write": 3}, "dimensions": {"read": 3, "write": 3}, "multiple_sheets": {"read": 3, "write": 3}, "merged_cells": {"read": 3, "write": 3}, "conditional_formatting": {"read": 3, "write": 3}, "data_validation": {"read": 3, "write": 3}, "hyperlinks": {"read": 3, "write": 3}, "images": {"read": 3, "write": 3}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": 3, "write": 3}, "freeze_panes": {"read": 3, "write": 3}, "named_ranges": {"read": 3, "write": 3}, "tables": {"read": 3, "write": 3}, "sheet_protection": {"read": 3, "write": 3}, "page_setup": {"read": 3, "write": 3}, "chart_anchor": {"read": 3, "write": 3}}, "xlsxwriter": {"cell_values": {"read": null, "write": 3}, "formulas": {"read": null, "write": 3}, "text_formatting": {"read": null, "write": 3}, "background_colors": {"read": null, "write": 3}, "number_formats": {"read": null, "write": 3}, "alignment": {"read": null, "write": 1}, "borders": {"read": null, "write": 3}, "dimensions": {"read": null, "write": 3}, "multiple_sheets": {"read": null, "write": 3}, "merged_cells": {"read": null, "write": 3}, "conditional_formatting": {"read": null, "write": 3}, "data_validation": {"read": null, "write": 3}, "hyperlinks": {"read": null, "write": 3}, "images": {"read": null, "write": 3}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": null, "write": 3}, "freeze_panes": {"read": null, "write": 3}, "named_ranges": {"read": null, "write": 0}, "tables": {"read": null, "write": 0}, "sheet_protection": {"read": null, "write": 0}, "page_setup": {"read": null, "write": 0}, "chart_anchor": {"read": null, "write": 0}}, "python-calamine": {"cell_values": {"read": 1, "write": null}, "formulas": {"read": 0, "write": null}, "text_formatting": {"read": 0, "write": null}, "background_colors": {"read": 0, "write": null}, "number_formats": {"read": 0, "write": null}, "alignment": {"read": 0, "write": null}, "borders": {"read": 0, "write": null}, "dimensions": {"read": 0, "write": null}, "multiple_sheets": {"read": 3, "write": null}, "merged_cells": {"read": 0, "write": null}, "conditional_formatting": {"read": 0, "write": null}, "data_validation": {"read": 0, "write": null}, "hyperlinks": {"read": 0, "write": null}, "images": {"read": 0, "write": null}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": 0, "write": null}, "freeze_panes": {"read": 0, "write": null}, "named_ranges": {"read": 0, "write": null}, "tables": {"read": 0, "write": null}, "sheet_protection": {"read": 0, "write": null}, "page_setup": {"read": 0, "write": null}, "chart_anchor": {"read": 0, "write": null}}, "aspose-cells-foss": {"cell_values": {"read": 1, "write": 3}, "formulas": {"read": 3, "write": 3}, "text_formatting": {"read": 1, "write": 0}, "background_colors": {"read": 3, "write": 3}, "number_formats": {"read": 3, "write": 3}, "alignment": {"read": 1, "write": 1}, "borders": {"read": 1, "write": 1}, "dimensions": {"read": 1, "write": 3}, "multiple_sheets": {"read": 3, "write": 3}, "merged_cells": {"read": 3, "write": 3}, "conditional_formatting": {"read": 3, "write": 3}, "data_validation": {"read": 3, "write": 3}, "hyperlinks": {"read": 0, "write": 3}, "images": {"read": 0, "write": 0}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": 3, "write": 0}, "freeze_panes": {"read": 3, "write": 3}, "named_ranges": {"read": 2, "write": 3}, "tables": {"read": 1, "write": 1}, "sheet_protection": {"read": 3, "write": 3}, "page_setup": {"read": 1, "write": 0}, "chart_anchor": {"read": 3, "write": 3}}, "wolfxl": {"cell_values": {"read": 3, "write": 3}, "formulas": {"read": 3, "write": 3}, "text_formatting": {"read": 3, "write": 3}, "background_colors": {"read": 3, "write": 3}, "number_formats": {"read": 3, "write": 3}, "alignment": {"read": 3, "write": 3}, "borders": {"read": 3, "write": 3}, "dimensions": {"read": 3, "write": 3}, "multiple_sheets": {"read": 3, "write": 3}, "merged_cells": {"read": 3, "write": 3}, "conditional_formatting": {"read": 0, "write": 3}, "data_validation": {"read": 3, "write": 3}, "hyperlinks": {"read": 3, "write": 3}, "images": {"read": 3, "write": 3}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": 3, "write": 3}, "freeze_panes": {"read": 3, "write": 3}, "named_ranges": {"read": 3, "write": 2}, "tables": {"read": 3, "write": 3}, "sheet_protection": {"read": 3, "write": 3}, "page_setup": {"read": 3, "write": 2}, "chart_anchor": {"read": 3, "write": 3}}, "pylightxl": {"cell_values": {"read": 3, "write": 0}, "formulas": {"read": 0, "write": 3}, "text_formatting": {"read": 0, "write": 0}, "background_colors": {"read": 0, "write": 0}, "number_formats": {"read": 0, "write": 0}, "alignment": {"read": 0, "write": 0}, "borders": {"read": 0, "write": 0}, "dimensions": {"read": 0, "write": 0}, "multiple_sheets": {"read": 3, "write": 3}, "merged_cells": {"read": 0, "write": 0}, "conditional_formatting": {"read": 0, "write": 0}, "data_validation": {"read": 0, "write": 0}, "hyperlinks": {"read": 0, "write": 0}, "images": {"read": 0, "write": 0}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": 0, "write": 0}, "freeze_panes": {"read": 0, "write": 0}, "named_ranges": {"read": 0, "write": 0}, "tables": {"read": 0, "write": 0}, "sheet_protection": {"read": 0, "write": 0}, "page_setup": {"read": 0, "write": 0}, "chart_anchor": {"read": 0, "write": 0}}, "xlrd": {"cell_values": {"read": null, "write": null}, "formulas": {"read": null, "write": null}, "text_formatting": {"read": null, "write": null}, "background_colors": {"read": null, "write": null}, "number_formats": {"read": null, "write": null}, "alignment": {"read": null, "write": null}, "borders": {"read": null, "write": null}, "dimensions": {"read": null, "write": null}, "multiple_sheets": {"read": null, "write": null}, "merged_cells": {"read": null, "write": null}, "conditional_formatting": {"read": null, "write": null}, "data_validation": {"read": null, "write": null}, "hyperlinks": {"read": null, "write": null}, "images": {"read": null, "write": null}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": null, "write": null}, "freeze_panes": {"read": null, "write": null}, "named_ranges": {"read": null, "write": null}, "tables": {"read": null, "write": null}, "sheet_protection": {"read": null, "write": null}, "page_setup": {"read": null, "write": null}, "chart_anchor": {"read": null, "write": null}}, "pyexcel": {"cell_values": {"read": 3, "write": 0}, "formulas": {"read": 0, "write": 3}, "text_formatting": {"read": 0, "write": 0}, "background_colors": {"read": 0, "write": 0}, "number_formats": {"read": 0, "write": 0}, "alignment": {"read": 0, "write": 0}, "borders": {"read": 0, "write": 0}, "dimensions": {"read": 0, "write": 0}, "multiple_sheets": {"read": 3, "write": 3}, "merged_cells": {"read": 0, "write": 0}, "conditional_formatting": {"read": 0, "write": 0}, "data_validation": {"read": 0, "write": 0}, "hyperlinks": {"read": 0, "write": 0}, "images": {"read": 0, "write": 0}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": 0, "write": 0}, "freeze_panes": {"read": 0, "write": 0}, "named_ranges": {"read": 0, "write": 0}, "tables": {"read": 0, "write": 0}, "sheet_protection": {"read": 0, "write": 0}, "page_setup": {"read": 0, "write": 0}, "chart_anchor": {"read": 0, "write": 0}}, "xlwt": {"cell_values": {"read": null, "write": 3}, "formulas": {"read": null, "write": 0}, "text_formatting": {"read": null, "write": 1}, "background_colors": {"read": null, "write": 1}, "number_formats": {"read": null, "write": 3}, "alignment": {"read": null, "write": 3}, "borders": {"read": null, "write": 1}, "dimensions": {"read": null, "write": 1}, "multiple_sheets": {"read": null, "write": 3}, "merged_cells": {"read": null, "write": 0}, "conditional_formatting": {"read": null, "write": 0}, "data_validation": {"read": null, "write": 0}, "hyperlinks": {"read": null, "write": 0}, "images": {"read": null, "write": 0}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": null, "write": 0}, "freeze_panes": {"read": null, "write": 0}, "named_ranges": {"read": null, "write": 0}, "tables": {"read": null, "write": 0}, "sheet_protection": {"read": null, "write": 0}, "page_setup": {"read": null, "write": 0}, "chart_anchor": {"read": null, "write": 0}}, "pandas": {"cell_values": {"read": 1, "write": 3}, "formulas": {"read": 0, "write": 3}, "text_formatting": {"read": 0, "write": 0}, "background_colors": {"read": 0, "write": 0}, "number_formats": {"read": 0, "write": 0}, "alignment": {"read": 0, "write": 0}, "borders": {"read": 0, "write": 0}, "dimensions": {"read": 0, "write": 0}, "multiple_sheets": {"read": 3, "write": 3}, "merged_cells": {"read": 0, "write": 0}, "conditional_formatting": {"read": 0, "write": 0}, "data_validation": {"read": 0, "write": 0}, "hyperlinks": {"read": 0, "write": 0}, "images": {"read": 0, "write": 0}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": 0, "write": 0}, "freeze_panes": {"read": 0, "write": 0}, "named_ranges": {"read": 0, "write": 0}, "tables": {"read": 0, "write": 0}, "sheet_protection": {"read": 0, "write": 0}, "page_setup": {"read": 0, "write": 0}, "chart_anchor": {"read": 0, "write": 0}}, "xlsxwriter-constmem": {"cell_values": {"read": null, "write": 3}, "formulas": {"read": null, "write": 3}, "text_formatting": {"read": null, "write": 3}, "background_colors": {"read": null, "write": 3}, "number_formats": {"read": null, "write": 3}, "alignment": {"read": null, "write": 1}, "borders": {"read": null, "write": 3}, "dimensions": {"read": null, "write": 1}, "multiple_sheets": {"read": null, "write": 3}, "merged_cells": {"read": null, "write": 3}, "conditional_formatting": {"read": null, "write": 3}, "data_validation": {"read": null, "write": 3}, "hyperlinks": {"read": null, "write": 3}, "images": {"read": null, "write": 0}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": null, "write": 0}, "freeze_panes": {"read": null, "write": 3}, "named_ranges": {"read": null, "write": 0}, "tables": {"read": null, "write": 0}, "sheet_protection": {"read": null, "write": 0}, "page_setup": {"read": null, "write": 0}, "chart_anchor": {"read": null, "write": 0}}, "openpyxl-readonly": {"cell_values": {"read": 3, "write": null}, "formulas": {"read": 3, "write": null}, "text_formatting": {"read": 0, "write": null}, "background_colors": {"read": 0, "write": null}, "number_formats": {"read": 0, "write": null}, "alignment": {"read": 0, "write": null}, "borders": {"read": 0, "write": null}, "dimensions": {"read": 0, "write": null}, "multiple_sheets": {"read": 3, "write": null}, "merged_cells": {"read": 0, "write": null}, "conditional_formatting": {"read": 0, "write": null}, "data_validation": {"read": 0, "write": null}, "hyperlinks": {"read": 0, "write": null}, "images": {"read": 0, "write": null}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": 0, "write": null}, "freeze_panes": {"read": 0, "write": null}, "named_ranges": {"read": 0, "write": null}, "tables": {"read": 0, "write": null}, "sheet_protection": {"read": 0, "write": null}, "page_setup": {"read": 0, "write": null}, "chart_anchor": {"read": 0, "write": null}}, "polars": {"cell_values": {"read": 1, "write": null}, "formulas": {"read": 0, "write": null}, "text_formatting": {"read": 0, "write": null}, "background_colors": {"read": 0, "write": null}, "number_formats": {"read": 0, "write": null}, "alignment": {"read": 0, "write": null}, "borders": {"read": 0, "write": null}, "dimensions": {"read": 0, "write": null}, "multiple_sheets": {"read": 1, "write": null}, "merged_cells": {"read": 0, "write": null}, "conditional_formatting": {"read": 0, "write": null}, "data_validation": {"read": 0, "write": null}, "hyperlinks": {"read": 0, "write": null}, "images": {"read": 0, "write": null}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": 0, "write": null}, "freeze_panes": {"read": 0, "write": null}, "named_ranges": {"read": 0, "write": null}, "tables": {"read": 0, "write": null}, "sheet_protection": {"read": 0, "write": null}, "page_setup": {"read": 0, "write": null}, "chart_anchor": {"read": 0, "write": null}}, "tablib": {"cell_values": {"read": 3, "write": 3}, "formulas": {"read": 0, "write": 3}, "text_formatting": {"read": 0, "write": 0}, "background_colors": {"read": 0, "write": 0}, "number_formats": {"read": 0, "write": 0}, "alignment": {"read": 0, "write": 0}, "borders": {"read": 0, "write": 0}, "dimensions": {"read": 0, "write": 0}, "multiple_sheets": {"read": 3, "write": 3}, "merged_cells": {"read": 0, "write": 0}, "conditional_formatting": {"read": 0, "write": 0}, "data_validation": {"read": 0, "write": 0}, "hyperlinks": {"read": 0, "write": 0}, "images": {"read": 0, "write": 0}, "pivot_tables": {"read": null, "write": null}, "comments": {"read": 0, "write": 0}, "freeze_panes": {"read": 0, "write": 0}, "named_ranges": {"read": 0, "write": 0}, "tables": {"read": 0, "write": 0}, "sheet_protection": {"read": 0, "write": 0}, "page_setup": {"read": 0, "write": 0}, "chart_anchor": {"read": 0, "write": 0}}}} diff --git a/results-2026-09-08/xlsx/matrix.csv b/results-2026-09-08/xlsx/matrix.csv new file mode 100644 index 0000000..99fa462 --- /dev/null +++ b/results-2026-09-08/xlsx/matrix.csv @@ -0,0 +1,309 @@ +library,feature,read_score,write_score +openpyxl,cell_values,3,3 +xlsxwriter,cell_values,,3 +python-calamine,cell_values,1, +aspose-cells-foss,cell_values,1,3 +wolfxl,cell_values,3,3 +pylightxl,cell_values,3,0 +xlrd,cell_values,, +pyexcel,cell_values,3,0 +xlwt,cell_values,,3 +pandas,cell_values,1,3 +xlsxwriter-constmem,cell_values,,3 +openpyxl-readonly,cell_values,3, +polars,cell_values,1, +tablib,cell_values,3,3 +openpyxl,formulas,3,3 +xlsxwriter,formulas,,3 +python-calamine,formulas,0, +aspose-cells-foss,formulas,3,3 +wolfxl,formulas,3,3 +pylightxl,formulas,0,3 +xlrd,formulas,, +pyexcel,formulas,0,3 +xlwt,formulas,,0 +pandas,formulas,0,3 +xlsxwriter-constmem,formulas,,3 +openpyxl-readonly,formulas,3, +polars,formulas,0, +tablib,formulas,0,3 +openpyxl,text_formatting,3,3 +xlsxwriter,text_formatting,,3 +python-calamine,text_formatting,0, +aspose-cells-foss,text_formatting,1,0 +wolfxl,text_formatting,3,3 +pylightxl,text_formatting,0,0 +xlrd,text_formatting,, +pyexcel,text_formatting,0,0 +xlwt,text_formatting,,1 +pandas,text_formatting,0,0 +xlsxwriter-constmem,text_formatting,,3 +openpyxl-readonly,text_formatting,0, +polars,text_formatting,0, +tablib,text_formatting,0,0 +openpyxl,background_colors,3,3 +xlsxwriter,background_colors,,3 +python-calamine,background_colors,0, +aspose-cells-foss,background_colors,3,3 +wolfxl,background_colors,3,3 +pylightxl,background_colors,0,0 +xlrd,background_colors,, +pyexcel,background_colors,0,0 +xlwt,background_colors,,1 +pandas,background_colors,0,0 +xlsxwriter-constmem,background_colors,,3 +openpyxl-readonly,background_colors,0, +polars,background_colors,0, +tablib,background_colors,0,0 +openpyxl,number_formats,3,3 +xlsxwriter,number_formats,,3 +python-calamine,number_formats,0, +aspose-cells-foss,number_formats,3,3 +wolfxl,number_formats,3,3 +pylightxl,number_formats,0,0 +xlrd,number_formats,, +pyexcel,number_formats,0,0 +xlwt,number_formats,,3 +pandas,number_formats,0,0 +xlsxwriter-constmem,number_formats,,3 +openpyxl-readonly,number_formats,0, +polars,number_formats,0, +tablib,number_formats,0,0 +openpyxl,alignment,3,3 +xlsxwriter,alignment,,1 +python-calamine,alignment,0, +aspose-cells-foss,alignment,1,1 +wolfxl,alignment,3,3 +pylightxl,alignment,0,0 +xlrd,alignment,, +pyexcel,alignment,0,0 +xlwt,alignment,,3 +pandas,alignment,0,0 +xlsxwriter-constmem,alignment,,1 +openpyxl-readonly,alignment,0, +polars,alignment,0, +tablib,alignment,0,0 +openpyxl,borders,3,3 +xlsxwriter,borders,,3 +python-calamine,borders,0, +aspose-cells-foss,borders,1,1 +wolfxl,borders,3,3 +pylightxl,borders,0,0 +xlrd,borders,, +pyexcel,borders,0,0 +xlwt,borders,,1 +pandas,borders,0,0 +xlsxwriter-constmem,borders,,3 +openpyxl-readonly,borders,0, +polars,borders,0, +tablib,borders,0,0 +openpyxl,dimensions,3,3 +xlsxwriter,dimensions,,3 +python-calamine,dimensions,0, +aspose-cells-foss,dimensions,1,3 +wolfxl,dimensions,3,3 +pylightxl,dimensions,0,0 +xlrd,dimensions,, +pyexcel,dimensions,0,0 +xlwt,dimensions,,1 +pandas,dimensions,0,0 +xlsxwriter-constmem,dimensions,,1 +openpyxl-readonly,dimensions,0, +polars,dimensions,0, +tablib,dimensions,0,0 +openpyxl,multiple_sheets,3,3 +xlsxwriter,multiple_sheets,,3 +python-calamine,multiple_sheets,3, +aspose-cells-foss,multiple_sheets,3,3 +wolfxl,multiple_sheets,3,3 +pylightxl,multiple_sheets,3,3 +xlrd,multiple_sheets,, +pyexcel,multiple_sheets,3,3 +xlwt,multiple_sheets,,3 +pandas,multiple_sheets,3,3 +xlsxwriter-constmem,multiple_sheets,,3 +openpyxl-readonly,multiple_sheets,3, +polars,multiple_sheets,1, +tablib,multiple_sheets,3,3 +openpyxl,merged_cells,3,3 +xlsxwriter,merged_cells,,3 +python-calamine,merged_cells,0, +aspose-cells-foss,merged_cells,3,3 +wolfxl,merged_cells,3,3 +pylightxl,merged_cells,0,0 +xlrd,merged_cells,, +pyexcel,merged_cells,0,0 +xlwt,merged_cells,,0 +pandas,merged_cells,0,0 +xlsxwriter-constmem,merged_cells,,3 +openpyxl-readonly,merged_cells,0, +polars,merged_cells,0, +tablib,merged_cells,0,0 +openpyxl,conditional_formatting,3,3 +xlsxwriter,conditional_formatting,,3 +python-calamine,conditional_formatting,0, +aspose-cells-foss,conditional_formatting,3,3 +wolfxl,conditional_formatting,0,3 +pylightxl,conditional_formatting,0,0 +xlrd,conditional_formatting,, +pyexcel,conditional_formatting,0,0 +xlwt,conditional_formatting,,0 +pandas,conditional_formatting,0,0 +xlsxwriter-constmem,conditional_formatting,,3 +openpyxl-readonly,conditional_formatting,0, +polars,conditional_formatting,0, +tablib,conditional_formatting,0,0 +openpyxl,data_validation,3,3 +xlsxwriter,data_validation,,3 +python-calamine,data_validation,0, +aspose-cells-foss,data_validation,3,3 +wolfxl,data_validation,3,3 +pylightxl,data_validation,0,0 +xlrd,data_validation,, +pyexcel,data_validation,0,0 +xlwt,data_validation,,0 +pandas,data_validation,0,0 +xlsxwriter-constmem,data_validation,,3 +openpyxl-readonly,data_validation,0, +polars,data_validation,0, +tablib,data_validation,0,0 +openpyxl,hyperlinks,3,3 +xlsxwriter,hyperlinks,,3 +python-calamine,hyperlinks,0, +aspose-cells-foss,hyperlinks,0,3 +wolfxl,hyperlinks,3,3 +pylightxl,hyperlinks,0,0 +xlrd,hyperlinks,, +pyexcel,hyperlinks,0,0 +xlwt,hyperlinks,,0 +pandas,hyperlinks,0,0 +xlsxwriter-constmem,hyperlinks,,3 +openpyxl-readonly,hyperlinks,0, +polars,hyperlinks,0, +tablib,hyperlinks,0,0 +openpyxl,images,3,3 +xlsxwriter,images,,3 +python-calamine,images,0, +aspose-cells-foss,images,0,0 +wolfxl,images,3,3 +pylightxl,images,0,0 +xlrd,images,, +pyexcel,images,0,0 +xlwt,images,,0 +pandas,images,0,0 +xlsxwriter-constmem,images,,0 +openpyxl-readonly,images,0, +polars,images,0, +tablib,images,0,0 +openpyxl,pivot_tables,, +xlsxwriter,pivot_tables,, +python-calamine,pivot_tables,, +aspose-cells-foss,pivot_tables,, +wolfxl,pivot_tables,, +pylightxl,pivot_tables,, +xlrd,pivot_tables,, +pyexcel,pivot_tables,, +xlwt,pivot_tables,, +pandas,pivot_tables,, +xlsxwriter-constmem,pivot_tables,, +openpyxl-readonly,pivot_tables,, +polars,pivot_tables,, +tablib,pivot_tables,, +openpyxl,comments,3,3 +xlsxwriter,comments,,3 +python-calamine,comments,0, +aspose-cells-foss,comments,3,0 +wolfxl,comments,3,3 +pylightxl,comments,0,0 +xlrd,comments,, +pyexcel,comments,0,0 +xlwt,comments,,0 +pandas,comments,0,0 +xlsxwriter-constmem,comments,,0 +openpyxl-readonly,comments,0, +polars,comments,0, +tablib,comments,0,0 +openpyxl,freeze_panes,3,3 +xlsxwriter,freeze_panes,,3 +python-calamine,freeze_panes,0, +aspose-cells-foss,freeze_panes,3,3 +wolfxl,freeze_panes,3,3 +pylightxl,freeze_panes,0,0 +xlrd,freeze_panes,, +pyexcel,freeze_panes,0,0 +xlwt,freeze_panes,,0 +pandas,freeze_panes,0,0 +xlsxwriter-constmem,freeze_panes,,3 +openpyxl-readonly,freeze_panes,0, +polars,freeze_panes,0, +tablib,freeze_panes,0,0 +openpyxl,named_ranges,3,3 +xlsxwriter,named_ranges,,0 +python-calamine,named_ranges,0, +aspose-cells-foss,named_ranges,2,3 +wolfxl,named_ranges,3,2 +pylightxl,named_ranges,0,0 +xlrd,named_ranges,, +pyexcel,named_ranges,0,0 +xlwt,named_ranges,,0 +pandas,named_ranges,0,0 +xlsxwriter-constmem,named_ranges,,0 +openpyxl-readonly,named_ranges,0, +polars,named_ranges,0, +tablib,named_ranges,0,0 +openpyxl,tables,3,3 +xlsxwriter,tables,,0 +python-calamine,tables,0, +aspose-cells-foss,tables,1,1 +wolfxl,tables,3,3 +pylightxl,tables,0,0 +xlrd,tables,, +pyexcel,tables,0,0 +xlwt,tables,,0 +pandas,tables,0,0 +xlsxwriter-constmem,tables,,0 +openpyxl-readonly,tables,0, +polars,tables,0, +tablib,tables,0,0 +openpyxl,sheet_protection,3,3 +xlsxwriter,sheet_protection,,0 +python-calamine,sheet_protection,0, +aspose-cells-foss,sheet_protection,3,3 +wolfxl,sheet_protection,3,3 +pylightxl,sheet_protection,0,0 +xlrd,sheet_protection,, +pyexcel,sheet_protection,0,0 +xlwt,sheet_protection,,0 +pandas,sheet_protection,0,0 +xlsxwriter-constmem,sheet_protection,,0 +openpyxl-readonly,sheet_protection,0, +polars,sheet_protection,0, +tablib,sheet_protection,0,0 +openpyxl,page_setup,3,3 +xlsxwriter,page_setup,,0 +python-calamine,page_setup,0, +aspose-cells-foss,page_setup,1,0 +wolfxl,page_setup,3,2 +pylightxl,page_setup,0,0 +xlrd,page_setup,, +pyexcel,page_setup,0,0 +xlwt,page_setup,,0 +pandas,page_setup,0,0 +xlsxwriter-constmem,page_setup,,0 +openpyxl-readonly,page_setup,0, +polars,page_setup,0, +tablib,page_setup,0,0 +openpyxl,chart_anchor,3,3 +xlsxwriter,chart_anchor,,0 +python-calamine,chart_anchor,0, +aspose-cells-foss,chart_anchor,3,3 +wolfxl,chart_anchor,3,3 +pylightxl,chart_anchor,0,0 +xlrd,chart_anchor,, +pyexcel,chart_anchor,0,0 +xlwt,chart_anchor,,0 +pandas,chart_anchor,0,0 +xlsxwriter-constmem,chart_anchor,,0 +openpyxl-readonly,chart_anchor,0, +polars,chart_anchor,0, +tablib,chart_anchor,0,0 \ No newline at end of file diff --git a/results-2026-09-08/xlsx/results.json b/results-2026-09-08/xlsx/results.json new file mode 100644 index 0000000..7ba96a6 --- /dev/null +++ b/results-2026-09-08/xlsx/results.json @@ -0,0 +1,81010 @@ +{ + "metadata": { + "benchmark_version": "0.1.0", + "run_date": "2026-09-08T05:35:34.204256+00:00", + "excel_version": "16.105.3", + "platform": "Darwin-arm64", + "profile": "xlsx" + }, + "libraries": { + "openpyxl": { + "name": "openpyxl", + "version": "3.1.5", + "language": "python", + "capabilities": [ + "write", + "read" + ] + }, + "xlsxwriter": { + "name": "xlsxwriter", + "version": "3.2.9", + "language": "python", + "capabilities": [ + "write" + ] + }, + "python-calamine": { + "name": "python-calamine", + "version": "0.6.1", + "language": "python", + "capabilities": [ + "read" + ] + }, + "aspose-cells-foss": { + "name": "aspose-cells-foss", + "version": "26.7.0", + "language": "python", + "capabilities": [ + "write", + "read" + ] + }, + "wolfxl": { + "name": "wolfxl", + "version": "2.1.0", + "language": "python", + "capabilities": [ + "modify", + "write", + "read" + ] + }, + "pylightxl": { + "name": "pylightxl", + "version": "1.61", + "language": "python", + "capabilities": [ + "write", + "read" + ] + }, + "xlrd": { + "name": "xlrd", + "version": "2.0.2", + "language": "python", + "capabilities": [ + "read" + ] + }, + "pyexcel": { + "name": "pyexcel", + "version": "0.7.4", + "language": "python", + "capabilities": [ + "write", + "read" + ] + }, + "xlwt": { + "name": "xlwt", + "version": "1.3.0", + "language": "python", + "capabilities": [ + "write" + ] + }, + "pandas": { + "name": "pandas", + "version": "3.0.0", + "language": "python", + "capabilities": [ + "write", + "read" + ] + }, + "xlsxwriter-constmem": { + "name": "xlsxwriter-constmem", + "version": "3.2.9", + "language": "python", + "capabilities": [ + "write" + ] + }, + "openpyxl-readonly": { + "name": "openpyxl-readonly", + "version": "3.1.5", + "language": "python", + "capabilities": [ + "read" + ] + }, + "polars": { + "name": "polars", + "version": "1.38.1", + "language": "python", + "capabilities": [ + "read" + ] + }, + "tablib": { + "name": "tablib", + "version": "3.9.0", + "language": "python", + "capabilities": [ + "write", + "read" + ] + } + }, + "results": [ + { + "feature": "cell_values", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "string_simple": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + }, + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "read": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + }, + "write": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "read": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + }, + "write": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + }, + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + }, + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + }, + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "cell_values", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "string_simple": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "write": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "write": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "cell_values", + "library": "python-calamine", + "scores": { + "read": 1, + "write": null + }, + "test_cases": { + "string_simple": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "read": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "read": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "read": { + "passed": false, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "error_div0", + "sheet": "cell_values", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'error', 'value': '#DIV/0!'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "read": { + "passed": false, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "error_na", + "sheet": "cell_values", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'error', 'value': '#N/A'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "read": { + "passed": false, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "error_value", + "sheet": "cell_values", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'error', 'value': '#VALUE!'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": "Known limitation: python-calamine can surface formula error cells as blank values in current API responses." + }, + { + "feature": "cell_values", + "library": "aspose-cells-foss", + "scores": { + "read": 1, + "write": 3 + }, + "test_cases": { + "string_simple": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + }, + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "read": { + "passed": false, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "number", + "value": 46057 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "date_standard", + "sheet": "cell_values", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'date', 'value': '2026-02-04'}, actual={'type': 'number', 'value': 46057}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Date - standard" + }, + "write": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "read": { + "passed": false, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "number", + "value": 46057.43802083333 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "datetime", + "sheet": "cell_values", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'datetime', 'value': '2026-02-04T10:30:45'}, actual={'type': 'number', 'value': 46057.43802083333}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "DateTime - with time" + }, + "write": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + }, + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + }, + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + }, + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "cell_values", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "string_simple": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + }, + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "read": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + }, + "write": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "read": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + }, + "write": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + }, + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + }, + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + }, + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "cell_values", + "library": "pylightxl", + "scores": { + "read": 3, + "write": 0 + }, + "test_cases": { + "string_simple": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + }, + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_simple", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + }, + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_unicode", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + }, + "write": { + "passed": false, + "expected": { + "type": "blank" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_empty", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + }, + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_long", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + }, + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_newline", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + }, + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_integer", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + }, + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_float", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + }, + "write": { + "passed": false, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_negative", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + }, + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_large", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + }, + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_scientific", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "read": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + }, + "write": { + "passed": false, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "date_standard", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "read": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + }, + "write": { + "passed": false, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "datetime", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + }, + "write": { + "passed": false, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "boolean_true", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + }, + "write": { + "passed": false, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "boolean_false", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + }, + "write": { + "passed": false, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "error_div0", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + }, + "write": { + "passed": false, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "error_na", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + }, + "write": { + "passed": false, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "error_value", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + }, + "write": { + "passed": false, + "expected": { + "type": "blank" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "blank", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": "Known limitation: pylightxl cell-values write has date/boolean/error fidelity limits due to writer encoding behavior." + }, + { + "feature": "cell_values", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "cell_values", + "library": "pyexcel", + "scores": { + "read": 3, + "write": 0 + }, + "test_cases": { + "string_simple": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + }, + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_simple", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + }, + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_unicode", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + }, + "write": { + "passed": false, + "expected": { + "type": "blank" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_empty", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + }, + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_long", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + }, + "write": { + "passed": false, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "string_newline", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + }, + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_integer", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + }, + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_float", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + }, + "write": { + "passed": false, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_negative", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + }, + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_large", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + }, + "write": { + "passed": false, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "number_scientific", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "read": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + }, + "write": { + "passed": false, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "date_standard", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "read": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + }, + "write": { + "passed": false, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "datetime", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + }, + "write": { + "passed": false, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "boolean_true", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + }, + "write": { + "passed": false, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "boolean_false", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + }, + "write": { + "passed": false, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "error_div0", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + }, + "write": { + "passed": false, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "error_na", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + }, + "write": { + "passed": false, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "error_value", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + }, + "write": { + "passed": false, + "expected": { + "type": "blank" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "cell_values", + "operation": "write", + "test_case_id": "blank", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "cell_values", + "library": "xlwt", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "string_simple": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "write": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "write": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "cell_values", + "library": "pandas", + "scores": { + "read": 1, + "write": 3 + }, + "test_cases": { + "string_simple": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + }, + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "read": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + }, + "write": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "read": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + }, + "write": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + }, + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + }, + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "read": { + "passed": false, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "error_div0", + "sheet": "cell_values", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'error', 'value': '#DIV/0!'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Error - #DIV/0!" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "read": { + "passed": false, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "error_na", + "sheet": "cell_values", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'error', 'value': '#N/A'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Error - #N/A" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "read": { + "passed": false, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "error_value", + "sheet": "cell_values", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'error', 'value': '#VALUE!'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Error - #VALUE!" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + }, + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "cell_values", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "string_simple": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "write": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "write": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "cell_values", + "library": "openpyxl-readonly", + "scores": { + "read": 3, + "write": null + }, + "test_cases": { + "string_simple": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "read": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "read": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "cell_values", + "library": "polars", + "scores": { + "read": 1, + "write": null + }, + "test_cases": { + "string_simple": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.141592654 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "read": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "read": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "read": { + "passed": false, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "error_div0", + "sheet": "cell_values", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'error', 'value': '#DIV/0!'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "read": { + "passed": false, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "error_na", + "sheet": "cell_values", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'error', 'value': '#N/A'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "read": { + "passed": false, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "cell_values", + "operation": "read", + "test_case_id": "error_value", + "sheet": "cell_values", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'error', 'value': '#VALUE!'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "cell_values", + "library": "tablib", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "string_simple": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Hello World" + }, + "actual": { + "type": "string", + "value": "Hello World" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - simple" + } + }, + "string_unicode": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "actual": { + "type": "string", + "value": "\u65e5\u672c\u8a9e\ud83c\udf89\u00e9mojis" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - unicode" + } + }, + "string_empty": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + }, + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - empty" + } + }, + "string_long": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "actual": { + "type": "string", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - long (1000 chars)" + } + }, + "string_newline": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "actual": { + "type": "string", + "value": "Line 1\nLine 2\nLine 3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "String - with newlines" + } + }, + "number_integer": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 42 + }, + "actual": { + "type": "number", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - integer" + } + }, + "number_float": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 3.14159265358979 + }, + "actual": { + "type": "number", + "value": 3.14159265358979 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - float" + } + }, + "number_negative": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": -100.5 + }, + "actual": { + "type": "number", + "value": -100.5 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - negative" + } + }, + "number_large": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1234567890123456 + }, + "actual": { + "type": "number", + "value": 1234567890123456 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - large" + } + }, + "number_scientific": { + "read": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + }, + "write": { + "passed": true, + "expected": { + "type": "number", + "value": 1.23e-10 + }, + "actual": { + "type": "number", + "value": 1.23e-10 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Number - scientific notation" + } + }, + "date_standard": { + "read": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + }, + "write": { + "passed": true, + "expected": { + "type": "date", + "value": "2026-02-04" + }, + "actual": { + "type": "date", + "value": "2026-02-04" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Date - standard" + } + }, + "datetime": { + "read": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + }, + "write": { + "passed": true, + "expected": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "actual": { + "type": "datetime", + "value": "2026-02-04T10:30:45" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DateTime - with time" + } + }, + "boolean_true": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + }, + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": true + }, + "actual": { + "type": "boolean", + "value": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - TRUE" + } + }, + "boolean_false": { + "read": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + }, + "write": { + "passed": true, + "expected": { + "type": "boolean", + "value": false + }, + "actual": { + "type": "boolean", + "value": false + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Boolean - FALSE" + } + }, + "error_div0": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#DIV/0!" + }, + "actual": { + "type": "error", + "value": "#DIV/0!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #DIV/0!" + } + }, + "error_na": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#N/A" + }, + "actual": { + "type": "error", + "value": "#N/A" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #N/A" + } + }, + "error_value": { + "read": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + }, + "write": { + "passed": true, + "expected": { + "type": "error", + "value": "#VALUE!" + }, + "actual": { + "type": "error", + "value": "#VALUE!" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Error - #VALUE!" + } + }, + "blank": { + "read": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + }, + "write": { + "passed": true, + "expected": { + "type": "blank" + }, + "actual": { + "type": "blank" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Blank cell" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "formula_sum": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "formula_sum": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "formula_sum": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_sum", + "sheet": "formulas", + "cell": "B2" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "error": "Expected formula, got blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cell_ref", + "sheet": "formulas", + "cell": "B3" + }, + "adapter_message": "RuntimeError: Expected formula, got blank", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "error": "Expected formula, got string" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_concat", + "sheet": "formulas", + "cell": "B4" + }, + "adapter_message": "RuntimeError: Expected formula, got string", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cross_sheet", + "sheet": "formulas", + "cell": "B5" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "formula_sum": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "formula_sum": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 3 + }, + "test_cases": { + "formula_sum": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_sum", + "sheet": "formulas", + "cell": "B2" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - SUM" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "error": "Expected formula, got error" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cell_ref", + "sheet": "formulas", + "cell": "B3" + }, + "adapter_message": "RuntimeError: Expected formula, got error", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cell reference" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "error": "Expected formula, got string" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_concat", + "sheet": "formulas", + "cell": "B4" + }, + "adapter_message": "RuntimeError: Expected formula, got string", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - concat" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cross_sheet", + "sheet": "formulas", + "cell": "B5" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cross sheet" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "formulas", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 3 + }, + "test_cases": { + "formula_sum": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_sum", + "sheet": "formulas", + "cell": "B2" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - SUM" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "error": "Expected formula, got error" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cell_ref", + "sheet": "formulas", + "cell": "B3" + }, + "adapter_message": "RuntimeError: Expected formula, got error", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cell reference" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "error": "Expected formula, got string" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_concat", + "sheet": "formulas", + "cell": "B4" + }, + "adapter_message": "RuntimeError: Expected formula, got string", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - concat" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cross_sheet", + "sheet": "formulas", + "cell": "B5" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cross sheet" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "formula_sum": { + "write": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "error": "Expected formula, got string" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "write", + "test_case_id": "formula_sum", + "sheet": "formulas", + "cell": "B2" + }, + "adapter_message": "RuntimeError: Expected formula, got string", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "write": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "error": "Expected formula, got string" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "write", + "test_case_id": "formula_cell_ref", + "sheet": "formulas", + "cell": "B3" + }, + "adapter_message": "RuntimeError: Expected formula, got string", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "write": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "error": "Expected formula, got string" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "write", + "test_case_id": "formula_concat", + "sheet": "formulas", + "cell": "B4" + }, + "adapter_message": "RuntimeError: Expected formula, got string", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "write": { + "passed": false, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "error": "Expected formula, got string" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "write", + "test_case_id": "formula_cross_sheet", + "sheet": "formulas", + "cell": "B5" + }, + "adapter_message": "RuntimeError: Expected formula, got string", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "pandas", + "scores": { + "read": 0, + "write": 3 + }, + "test_cases": { + "formula_sum": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_sum", + "sheet": "formulas", + "cell": "B2" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - SUM" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "error": "Expected formula, got blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cell_ref", + "sheet": "formulas", + "cell": "B3" + }, + "adapter_message": "RuntimeError: Expected formula, got blank", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cell reference" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "error": "Expected formula, got string" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_concat", + "sheet": "formulas", + "cell": "B4" + }, + "adapter_message": "RuntimeError: Expected formula, got string", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - concat" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cross_sheet", + "sheet": "formulas", + "cell": "B5" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cross sheet" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "formula_sum": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "openpyxl-readonly", + "scores": { + "read": 3, + "write": null + }, + "test_cases": { + "formula_sum": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "read": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "formula_sum": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_sum", + "sheet": "formulas", + "cell": "B2" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "error": "Expected formula, got blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cell_ref", + "sheet": "formulas", + "cell": "B3" + }, + "adapter_message": "RuntimeError: Expected formula, got blank", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "error": "Expected formula, got string" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_concat", + "sheet": "formulas", + "cell": "B4" + }, + "adapter_message": "RuntimeError: Expected formula, got string", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cross_sheet", + "sheet": "formulas", + "cell": "B5" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "formulas", + "library": "tablib", + "scores": { + "read": 0, + "write": 3 + }, + "test_cases": { + "formula_sum": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_sum", + "sheet": "formulas", + "cell": "B2" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - SUM" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "actual": { + "type": "formula", + "formula": "=SUM(1,2,3)" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - SUM" + } + }, + "formula_cell_ref": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "error": "Expected formula, got error" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cell_ref", + "sheet": "formulas", + "cell": "B3" + }, + "adapter_message": "RuntimeError: Expected formula, got error", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cell reference" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A3*2" + }, + "actual": { + "type": "formula", + "formula": "=A3*2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cell reference" + } + }, + "formula_concat": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "error": "Expected formula, got string" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_concat", + "sheet": "formulas", + "cell": "B4" + }, + "adapter_message": "RuntimeError: Expected formula, got string", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - concat" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "actual": { + "type": "formula", + "formula": "=A4&\" \"&A5" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - concat" + } + }, + "formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "error": "Expected formula, got number" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "formulas", + "operation": "read", + "test_case_id": "formula_cross_sheet", + "sheet": "formulas", + "cell": "B5" + }, + "adapter_message": "RuntimeError: Expected formula, got number", + "probable_cause": "Adapter could not return a comparable value for this assertion.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Formula - cross sheet" + }, + "write": { + "passed": true, + "expected": { + "type": "formula", + "formula": "='References'!B2" + }, + "actual": { + "type": "formula", + "formula": "='References'!B2" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Formula - cross sheet" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "bold": { + "read": { + "passed": true, + "expected": { + "bold": true + }, + "actual": { + "bold": true, + "font_name": "Aptos Narrow", + "font_size": 12.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold" + }, + "write": { + "passed": true, + "expected": { + "bold": true + }, + "actual": { + "bold": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "read": { + "passed": true, + "expected": { + "italic": true + }, + "actual": { + "italic": true, + "font_name": "Aptos Narrow", + "font_size": 12.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Italic" + }, + "write": { + "passed": true, + "expected": { + "italic": true + }, + "actual": { + "italic": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "read": { + "passed": true, + "expected": { + "underline": "single" + }, + "actual": { + "underline": "single", + "font_name": "Aptos Narrow", + "font_size": 12.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - single" + }, + "write": { + "passed": true, + "expected": { + "underline": "single" + }, + "actual": { + "underline": "single" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "read": { + "passed": true, + "expected": { + "underline": "double" + }, + "actual": { + "underline": "double", + "font_name": "Aptos Narrow", + "font_size": 12.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - double" + }, + "write": { + "passed": true, + "expected": { + "underline": "double" + }, + "actual": { + "underline": "double" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "read": { + "passed": true, + "expected": { + "strikethrough": true + }, + "actual": { + "strikethrough": true, + "font_name": "Aptos Narrow", + "font_size": 12.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Strikethrough" + }, + "write": { + "passed": true, + "expected": { + "strikethrough": true + }, + "actual": { + "strikethrough": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "read": { + "passed": true, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "bold": true, + "italic": true, + "font_name": "Aptos Narrow", + "font_size": 12.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold + Italic" + }, + "write": { + "passed": true, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "bold": true, + "italic": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "read": { + "passed": true, + "expected": { + "font_size": 8 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 8" + }, + "write": { + "passed": true, + "expected": { + "font_size": 8 + }, + "actual": { + "font_size": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "read": { + "passed": true, + "expected": { + "font_size": 14 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 14.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 14" + }, + "write": { + "passed": true, + "expected": { + "font_size": 14 + }, + "actual": { + "font_size": 14.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "read": { + "passed": true, + "expected": { + "font_size": 24 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 24.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 24" + }, + "write": { + "passed": true, + "expected": { + "font_size": 24 + }, + "actual": { + "font_size": 24.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "read": { + "passed": true, + "expected": { + "font_size": 36 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 36.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 36" + }, + "write": { + "passed": true, + "expected": { + "font_size": 36 + }, + "actual": { + "font_size": 36.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "read": { + "passed": true, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Arial", + "font_size": 12.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Arial" + }, + "write": { + "passed": true, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Arial" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "read": { + "passed": true, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Times New Roman", + "font_size": 12.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Times New Roman" + }, + "write": { + "passed": true, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Times New Roman" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "read": { + "passed": true, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Courier New", + "font_size": 12.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Courier New" + }, + "write": { + "passed": true, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Courier New" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "read": { + "passed": true, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - red" + }, + "write": { + "passed": true, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "read": { + "passed": true, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - blue" + }, + "write": { + "passed": true, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "read": { + "passed": true, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - green" + }, + "write": { + "passed": true, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "read": { + "passed": true, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + }, + "write": { + "passed": true, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "read": { + "passed": true, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "bold": true, + "font_name": "Aptos Narrow", + "font_size": 16.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + }, + "write": { + "passed": true, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "bold": true, + "font_size": 16.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "bold": { + "write": { + "passed": true, + "expected": { + "bold": true + }, + "actual": { + "bold": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "write": { + "passed": true, + "expected": { + "italic": true + }, + "actual": { + "italic": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "write": { + "passed": true, + "expected": { + "underline": "single" + }, + "actual": { + "underline": "single", + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "write": { + "passed": true, + "expected": { + "underline": "double" + }, + "actual": { + "underline": "double", + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "write": { + "passed": true, + "expected": { + "strikethrough": true + }, + "actual": { + "strikethrough": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "write": { + "passed": true, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "bold": true, + "italic": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "write": { + "passed": true, + "expected": { + "font_size": 8 + }, + "actual": { + "font_name": "Calibri", + "font_size": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "write": { + "passed": true, + "expected": { + "font_size": 14 + }, + "actual": { + "font_name": "Calibri", + "font_size": 14.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "write": { + "passed": true, + "expected": { + "font_size": 24 + }, + "actual": { + "font_name": "Calibri", + "font_size": 24.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "write": { + "passed": true, + "expected": { + "font_size": 36 + }, + "actual": { + "font_name": "Calibri", + "font_size": 36.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "write": { + "passed": true, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Arial", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "write": { + "passed": true, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Times New Roman", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "write": { + "passed": true, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Courier New", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "write": { + "passed": true, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "write": { + "passed": true, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "write": { + "passed": true, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "write": { + "passed": true, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "write": { + "passed": true, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "bold": true, + "font_name": "Calibri", + "font_size": 16.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "bold": { + "read": { + "passed": false, + "expected": { + "bold": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold", + "sheet": "text_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "read": { + "passed": false, + "expected": { + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "italic", + "sheet": "text_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "read": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_single", + "sheet": "text_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'single'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "read": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_double", + "sheet": "text_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'double'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "read": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "strikethrough", + "sheet": "text_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'strikethrough': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "read": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold_italic", + "sheet": "text_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "read": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_8", + "sheet": "text_formatting", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 8}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "read": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_14", + "sheet": "text_formatting", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 14}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "read": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_24", + "sheet": "text_formatting", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 24}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "read": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_36", + "sheet": "text_formatting", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 36}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "read": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_arial", + "sheet": "text_formatting", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "read": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_times", + "sheet": "text_formatting", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "read": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_courier", + "sheet": "text_formatting", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_red", + "sheet": "text_formatting", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "text_formatting", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "read": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_green", + "sheet": "text_formatting", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "text_formatting", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "read": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "combined", + "sheet": "text_formatting", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "aspose-cells-foss", + "scores": { + "read": 1, + "write": 0 + }, + "test_cases": { + "bold": { + "read": { + "passed": true, + "expected": { + "bold": true + }, + "actual": { + "bold": true, + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold" + }, + "write": { + "passed": false, + "expected": { + "bold": true + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "bold", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "read": { + "passed": true, + "expected": { + "italic": true + }, + "actual": { + "italic": true, + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Italic" + }, + "write": { + "passed": false, + "expected": { + "italic": true + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "italic", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "read": { + "passed": true, + "expected": { + "underline": "single" + }, + "actual": { + "underline": "single", + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - single" + }, + "write": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "underline_single", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "read": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": { + "underline": "single", + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_double", + "sheet": "text_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'double'}, actual={'underline': 'single', 'font_name': 'Aptos Narrow', 'font_size': 12.0, 'font_color': '#000000'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Underline - double" + }, + "write": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "underline_double", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "read": { + "passed": true, + "expected": { + "strikethrough": true + }, + "actual": { + "strikethrough": true, + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Strikethrough" + }, + "write": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "strikethrough", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "read": { + "passed": true, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "bold": true, + "italic": true, + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold + Italic" + }, + "write": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "bold_italic", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "read": { + "passed": true, + "expected": { + "font_size": 8 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 8.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 8" + }, + "write": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_8", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "read": { + "passed": true, + "expected": { + "font_size": 14 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 14.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 14" + }, + "write": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_14", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "read": { + "passed": true, + "expected": { + "font_size": 24 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 24.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 24" + }, + "write": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_24", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "read": { + "passed": true, + "expected": { + "font_size": 36 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 36.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 36" + }, + "write": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_36", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "read": { + "passed": true, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Arial", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Arial" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_arial", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "read": { + "passed": true, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Times New Roman", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Times New Roman" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_times", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "read": { + "passed": true, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Courier New", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Courier New" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_courier", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "read": { + "passed": true, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - red" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_red", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "read": { + "passed": true, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - blue" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_blue", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "read": { + "passed": true, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - green" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_green", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "read": { + "passed": true, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_custom", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "read": { + "passed": true, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "bold": true, + "font_name": "Aptos Narrow", + "font_size": 16.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + }, + "write": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "error": "aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "combined", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support write_cell_format: aspose-cells-foss supports only a single underline, not accounting or double variants.", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss supports only a single underline, not accounting or double variants.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "bold": { + "read": { + "passed": true, + "expected": { + "bold": true + }, + "actual": { + "bold": true, + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold" + }, + "write": { + "passed": true, + "expected": { + "bold": true + }, + "actual": { + "bold": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "read": { + "passed": true, + "expected": { + "italic": true + }, + "actual": { + "italic": true, + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Italic" + }, + "write": { + "passed": true, + "expected": { + "italic": true + }, + "actual": { + "italic": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "read": { + "passed": true, + "expected": { + "underline": "single" + }, + "actual": { + "underline": "single", + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - single" + }, + "write": { + "passed": true, + "expected": { + "underline": "single" + }, + "actual": { + "underline": "single" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "read": { + "passed": true, + "expected": { + "underline": "double" + }, + "actual": { + "underline": "double", + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - double" + }, + "write": { + "passed": true, + "expected": { + "underline": "double" + }, + "actual": { + "underline": "double" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "read": { + "passed": true, + "expected": { + "strikethrough": true + }, + "actual": { + "strikethrough": true, + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Strikethrough" + }, + "write": { + "passed": true, + "expected": { + "strikethrough": true + }, + "actual": { + "strikethrough": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "read": { + "passed": true, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "bold": true, + "italic": true, + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold + Italic" + }, + "write": { + "passed": true, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "bold": true, + "italic": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "read": { + "passed": true, + "expected": { + "font_size": 8 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 8.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 8" + }, + "write": { + "passed": true, + "expected": { + "font_size": 8 + }, + "actual": { + "font_size": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "read": { + "passed": true, + "expected": { + "font_size": 14 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 14.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 14" + }, + "write": { + "passed": true, + "expected": { + "font_size": 14 + }, + "actual": { + "font_size": 14.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "read": { + "passed": true, + "expected": { + "font_size": 24 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 24.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 24" + }, + "write": { + "passed": true, + "expected": { + "font_size": 24 + }, + "actual": { + "font_size": 24.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "read": { + "passed": true, + "expected": { + "font_size": 36 + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 36.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 36" + }, + "write": { + "passed": true, + "expected": { + "font_size": 36 + }, + "actual": { + "font_size": 36.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "read": { + "passed": true, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Arial", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Arial" + }, + "write": { + "passed": true, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Arial" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "read": { + "passed": true, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Times New Roman", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Times New Roman" + }, + "write": { + "passed": true, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Times New Roman" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "read": { + "passed": true, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Courier New", + "font_size": 12.0, + "font_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Courier New" + }, + "write": { + "passed": true, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Courier New" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "read": { + "passed": true, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - red" + }, + "write": { + "passed": true, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "read": { + "passed": true, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - blue" + }, + "write": { + "passed": true, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "read": { + "passed": true, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - green" + }, + "write": { + "passed": true, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "read": { + "passed": true, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_name": "Aptos Narrow", + "font_size": 12.0, + "font_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + }, + "write": { + "passed": true, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "read": { + "passed": true, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "bold": true, + "font_name": "Aptos Narrow", + "font_size": 16.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + }, + "write": { + "passed": true, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "bold": true, + "font_size": 16.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "bold": { + "read": { + "passed": false, + "expected": { + "bold": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold", + "sheet": "text_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold" + }, + "write": { + "passed": false, + "expected": { + "bold": true + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "bold", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "read": { + "passed": false, + "expected": { + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "italic", + "sheet": "text_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Italic" + }, + "write": { + "passed": false, + "expected": { + "italic": true + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "italic", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "read": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_single", + "sheet": "text_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'single'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - single" + }, + "write": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "underline_single", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "read": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_double", + "sheet": "text_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'double'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - double" + }, + "write": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "underline_double", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "read": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "strikethrough", + "sheet": "text_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'strikethrough': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Strikethrough" + }, + "write": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "strikethrough", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "read": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold_italic", + "sheet": "text_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold + Italic" + }, + "write": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "bold_italic", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "read": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_8", + "sheet": "text_formatting", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 8}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 8" + }, + "write": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_8", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "read": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_14", + "sheet": "text_formatting", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 14}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 14" + }, + "write": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_14", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "read": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_24", + "sheet": "text_formatting", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 24}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 24" + }, + "write": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_24", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "read": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_36", + "sheet": "text_formatting", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 36}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 36" + }, + "write": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_36", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "read": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_arial", + "sheet": "text_formatting", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_arial", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "read": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_times", + "sheet": "text_formatting", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_times", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "read": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_courier", + "sheet": "text_formatting", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_courier", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_red", + "sheet": "text_formatting", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - red" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_red", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "text_formatting", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_blue", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "read": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_green", + "sheet": "text_formatting", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - green" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_green", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "text_formatting", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_custom", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "read": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "combined", + "sheet": "text_formatting", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + }, + "write": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "combined", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "text_formatting", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "bold": { + "read": { + "passed": false, + "expected": { + "bold": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold", + "sheet": "text_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold" + }, + "write": { + "passed": false, + "expected": { + "bold": true + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "bold", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "read": { + "passed": false, + "expected": { + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "italic", + "sheet": "text_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Italic" + }, + "write": { + "passed": false, + "expected": { + "italic": true + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "italic", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "read": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_single", + "sheet": "text_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'single'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - single" + }, + "write": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "underline_single", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "read": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_double", + "sheet": "text_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'double'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - double" + }, + "write": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "underline_double", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "read": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "strikethrough", + "sheet": "text_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'strikethrough': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Strikethrough" + }, + "write": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "strikethrough", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "read": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold_italic", + "sheet": "text_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold + Italic" + }, + "write": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "bold_italic", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "read": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_8", + "sheet": "text_formatting", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 8}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 8" + }, + "write": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_8", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "read": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_14", + "sheet": "text_formatting", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 14}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 14" + }, + "write": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_14", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "read": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_24", + "sheet": "text_formatting", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 24}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 24" + }, + "write": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_24", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "read": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_36", + "sheet": "text_formatting", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 36}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 36" + }, + "write": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_36", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "read": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_arial", + "sheet": "text_formatting", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_arial", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "read": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_times", + "sheet": "text_formatting", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_times", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "read": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_courier", + "sheet": "text_formatting", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_courier", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_red", + "sheet": "text_formatting", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - red" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_red", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "text_formatting", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_blue", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "read": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_green", + "sheet": "text_formatting", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - green" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_green", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "text_formatting", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_custom", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "read": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "combined", + "sheet": "text_formatting", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + }, + "write": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "combined", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "xlwt", + "scores": { + "read": null, + "write": 1 + }, + "test_cases": { + "bold": { + "write": { + "passed": true, + "expected": { + "bold": true + }, + "actual": { + "bold": true, + "font_name": "Arial", + "font_size": 10.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "write": { + "passed": true, + "expected": { + "italic": true + }, + "actual": { + "italic": true, + "font_name": "Arial", + "font_size": 10.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "write": { + "passed": true, + "expected": { + "underline": "single" + }, + "actual": { + "underline": "single", + "font_name": "Arial", + "font_size": 10.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "write": { + "passed": true, + "expected": { + "underline": "double" + }, + "actual": { + "underline": "double", + "font_name": "Arial", + "font_size": 10.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "write": { + "passed": true, + "expected": { + "strikethrough": true + }, + "actual": { + "strikethrough": true, + "font_name": "Arial", + "font_size": 10.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "write": { + "passed": true, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "bold": true, + "italic": true, + "font_name": "Arial", + "font_size": 10.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "write": { + "passed": true, + "expected": { + "font_size": 8 + }, + "actual": { + "font_name": "Arial", + "font_size": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "write": { + "passed": true, + "expected": { + "font_size": 14 + }, + "actual": { + "font_name": "Arial", + "font_size": 14.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "write": { + "passed": true, + "expected": { + "font_size": 24 + }, + "actual": { + "font_name": "Arial", + "font_size": 24.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "write": { + "passed": true, + "expected": { + "font_size": 36 + }, + "actual": { + "font_name": "Arial", + "font_size": 36.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "write": { + "passed": true, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Arial", + "font_size": 10.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "write": { + "passed": true, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Times New Roman", + "font_size": 10.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "write": { + "passed": true, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Courier New", + "font_size": 10.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "write": { + "passed": true, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Arial", + "font_size": 10.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "write": { + "passed": true, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_name": "Arial", + "font_size": 10.0, + "font_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "write": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_name": "Arial", + "font_size": 10.0, + "font_color": "#008000" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_green", + "sheet": "text_formatting", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={'font_name': 'Arial', 'font_size': 10.0, 'font_color': '#008000'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "write": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_name": "Arial", + "font_size": 10.0, + "font_color": "#993300" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_custom", + "sheet": "text_formatting", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={'font_name': 'Arial', 'font_size': 10.0, 'font_color': '#993300'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "write": { + "passed": true, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "bold": true, + "font_name": "Arial", + "font_size": 16.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "bold": { + "read": { + "passed": false, + "expected": { + "bold": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold", + "sheet": "text_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold" + }, + "write": { + "passed": false, + "expected": { + "bold": true + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "bold", + "sheet": "text_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "read": { + "passed": false, + "expected": { + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "italic", + "sheet": "text_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Italic" + }, + "write": { + "passed": false, + "expected": { + "italic": true + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "italic", + "sheet": "text_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'italic': True}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "read": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_single", + "sheet": "text_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'single'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - single" + }, + "write": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "underline_single", + "sheet": "text_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'single'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "read": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_double", + "sheet": "text_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'double'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - double" + }, + "write": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "underline_double", + "sheet": "text_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'double'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "read": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "strikethrough", + "sheet": "text_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'strikethrough': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Strikethrough" + }, + "write": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "strikethrough", + "sheet": "text_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'strikethrough': True}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "read": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold_italic", + "sheet": "text_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold + Italic" + }, + "write": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "bold_italic", + "sheet": "text_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "read": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_8", + "sheet": "text_formatting", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 8}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 8" + }, + "write": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_8", + "sheet": "text_formatting", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 8}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "read": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_14", + "sheet": "text_formatting", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 14}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 14" + }, + "write": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_14", + "sheet": "text_formatting", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 14}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "read": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_24", + "sheet": "text_formatting", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 24}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 24" + }, + "write": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_24", + "sheet": "text_formatting", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 24}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "read": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_36", + "sheet": "text_formatting", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 36}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 36" + }, + "write": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_36", + "sheet": "text_formatting", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 36}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "read": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_arial", + "sheet": "text_formatting", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_arial", + "sheet": "text_formatting", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "read": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_times", + "sheet": "text_formatting", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_times", + "sheet": "text_formatting", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "read": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_courier", + "sheet": "text_formatting", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_courier", + "sheet": "text_formatting", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_red", + "sheet": "text_formatting", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - red" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_red", + "sheet": "text_formatting", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "text_formatting", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_blue", + "sheet": "text_formatting", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "read": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_green", + "sheet": "text_formatting", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - green" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_green", + "sheet": "text_formatting", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "text_formatting", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_custom", + "sheet": "text_formatting", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "read": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "combined", + "sheet": "text_formatting", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + }, + "write": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "combined", + "sheet": "text_formatting", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "bold": { + "write": { + "passed": true, + "expected": { + "bold": true + }, + "actual": { + "bold": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "write": { + "passed": true, + "expected": { + "italic": true + }, + "actual": { + "italic": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "write": { + "passed": true, + "expected": { + "underline": "single" + }, + "actual": { + "underline": "single", + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "write": { + "passed": true, + "expected": { + "underline": "double" + }, + "actual": { + "underline": "double", + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "write": { + "passed": true, + "expected": { + "strikethrough": true + }, + "actual": { + "strikethrough": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "write": { + "passed": true, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "bold": true, + "italic": true, + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "write": { + "passed": true, + "expected": { + "font_size": 8 + }, + "actual": { + "font_name": "Calibri", + "font_size": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "write": { + "passed": true, + "expected": { + "font_size": 14 + }, + "actual": { + "font_name": "Calibri", + "font_size": 14.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "write": { + "passed": true, + "expected": { + "font_size": 24 + }, + "actual": { + "font_name": "Calibri", + "font_size": 24.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "write": { + "passed": true, + "expected": { + "font_size": 36 + }, + "actual": { + "font_name": "Calibri", + "font_size": 36.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "write": { + "passed": true, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Arial", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "write": { + "passed": true, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Times New Roman", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "write": { + "passed": true, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Courier New", + "font_size": 11.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "write": { + "passed": true, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "write": { + "passed": true, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "write": { + "passed": true, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "write": { + "passed": true, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0, + "font_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "write": { + "passed": true, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "bold": true, + "font_name": "Calibri", + "font_size": 16.0, + "font_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "bold": { + "read": { + "passed": false, + "expected": { + "bold": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold", + "sheet": "text_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "read": { + "passed": false, + "expected": { + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "italic", + "sheet": "text_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "read": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_single", + "sheet": "text_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'single'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "read": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_double", + "sheet": "text_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'double'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "read": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "strikethrough", + "sheet": "text_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'strikethrough': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "read": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold_italic", + "sheet": "text_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "read": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_8", + "sheet": "text_formatting", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 8}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "read": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_14", + "sheet": "text_formatting", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 14}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "read": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_24", + "sheet": "text_formatting", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 24}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "read": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_36", + "sheet": "text_formatting", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 36}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "read": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_arial", + "sheet": "text_formatting", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "read": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_times", + "sheet": "text_formatting", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "read": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_courier", + "sheet": "text_formatting", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_red", + "sheet": "text_formatting", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "text_formatting", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "read": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_green", + "sheet": "text_formatting", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "text_formatting", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "read": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "combined", + "sheet": "text_formatting", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "bold": { + "read": { + "passed": false, + "expected": { + "bold": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold", + "sheet": "text_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "read": { + "passed": false, + "expected": { + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "italic", + "sheet": "text_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "read": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_single", + "sheet": "text_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'single'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "read": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_double", + "sheet": "text_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'double'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "read": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "strikethrough", + "sheet": "text_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'strikethrough': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "read": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold_italic", + "sheet": "text_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "read": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_8", + "sheet": "text_formatting", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 8}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "read": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_14", + "sheet": "text_formatting", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 14}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "read": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_24", + "sheet": "text_formatting", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 24}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "read": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_36", + "sheet": "text_formatting", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 36}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "read": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_arial", + "sheet": "text_formatting", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "read": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_times", + "sheet": "text_formatting", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "read": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_courier", + "sheet": "text_formatting", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_red", + "sheet": "text_formatting", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "text_formatting", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "read": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_green", + "sheet": "text_formatting", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "text_formatting", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "read": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "combined", + "sheet": "text_formatting", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "text_formatting", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "bold": { + "read": { + "passed": false, + "expected": { + "bold": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold", + "sheet": "text_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold" + }, + "write": { + "passed": false, + "expected": { + "bold": true + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "bold", + "sheet": "text_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Bold" + } + }, + "italic": { + "read": { + "passed": false, + "expected": { + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "italic", + "sheet": "text_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Italic" + }, + "write": { + "passed": false, + "expected": { + "italic": true + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "italic", + "sheet": "text_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'italic': True}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Italic" + } + }, + "underline_single": { + "read": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_single", + "sheet": "text_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'single'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - single" + }, + "write": { + "passed": false, + "expected": { + "underline": "single" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "underline_single", + "sheet": "text_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'single'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Underline - single" + } + }, + "underline_double": { + "read": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "underline_double", + "sheet": "text_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'double'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Underline - double" + }, + "write": { + "passed": false, + "expected": { + "underline": "double" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "underline_double", + "sheet": "text_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'underline': 'double'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Underline - double" + } + }, + "strikethrough": { + "read": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "strikethrough", + "sheet": "text_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'strikethrough': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Strikethrough" + }, + "write": { + "passed": false, + "expected": { + "strikethrough": true + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "strikethrough", + "sheet": "text_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'strikethrough': True}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Strikethrough" + } + }, + "bold_italic": { + "read": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "bold_italic", + "sheet": "text_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Bold + Italic" + }, + "write": { + "passed": false, + "expected": { + "bold": true, + "italic": true + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "bold_italic", + "sheet": "text_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'italic': True}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Bold + Italic" + } + }, + "font_size_8": { + "read": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_8", + "sheet": "text_formatting", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 8}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 8" + }, + "write": { + "passed": false, + "expected": { + "font_size": 8 + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_8", + "sheet": "text_formatting", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 8}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 8" + } + }, + "font_size_14": { + "read": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_14", + "sheet": "text_formatting", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 14}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 14" + }, + "write": { + "passed": false, + "expected": { + "font_size": 14 + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_14", + "sheet": "text_formatting", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 14}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 14" + } + }, + "font_size_24": { + "read": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_24", + "sheet": "text_formatting", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 24}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 24" + }, + "write": { + "passed": false, + "expected": { + "font_size": 24 + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_24", + "sheet": "text_formatting", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 24}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 24" + } + }, + "font_size_36": { + "read": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_size_36", + "sheet": "text_formatting", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 36}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 36" + }, + "write": { + "passed": false, + "expected": { + "font_size": 36 + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_size_36", + "sheet": "text_formatting", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_size': 36}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font size 36" + } + }, + "font_arial": { + "read": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_arial", + "sheet": "text_formatting", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Arial" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_arial", + "sheet": "text_formatting", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Arial'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Arial" + } + }, + "font_times": { + "read": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_times", + "sheet": "text_formatting", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Times New Roman" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_times", + "sheet": "text_formatting", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Times New Roman'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Times New Roman" + } + }, + "font_courier": { + "read": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "font_courier", + "sheet": "text_formatting", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + }, + "write": { + "passed": false, + "expected": { + "font_name": "Courier New" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "font_courier", + "sheet": "text_formatting", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_name': 'Courier New'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font - Courier New" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_red", + "sheet": "text_formatting", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - red" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_red", + "sheet": "text_formatting", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#FF0000'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - red" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "text_formatting", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#0000FF" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_blue", + "sheet": "text_formatting", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#0000FF'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - blue" + } + }, + "color_green": { + "read": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_green", + "sheet": "text_formatting", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - green" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#00FF00" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_green", + "sheet": "text_formatting", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#00FF00'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - green" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "text_formatting", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "font_color": "#8B4513" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "color_custom", + "sheet": "text_formatting", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'font_color': '#8B4513'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Font color - custom (#8B4513)" + } + }, + "combined": { + "read": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "read", + "test_case_id": "combined", + "sheet": "text_formatting", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + }, + "write": { + "passed": false, + "expected": { + "bold": true, + "font_size": 16, + "font_color": "#FF0000" + }, + "actual": { + "font_name": "Calibri", + "font_size": 11.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "text_formatting", + "operation": "write", + "test_case_id": "combined", + "sheet": "text_formatting", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'bold': True, 'font_size': 16, 'font_color': '#FF0000'}, actual={'font_name': 'Calibri', 'font_size': 11.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Combined - bold, 16pt, red" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "bg_red": { + "read": { + "passed": true, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - red" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "read": { + "passed": true, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "bg_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - blue" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "bg_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "read": { + "passed": true, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "bg_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - green" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "bg_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "read": { + "passed": true, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "bg_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - custom (#8B4513)" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "bg_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "bg_red": { + "write": { + "passed": true, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "write": { + "passed": true, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "bg_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "write": { + "passed": true, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "bg_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "write": { + "passed": true, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "bg_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "bg_red": { + "read": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_red", + "sheet": "background_colors", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "read": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_blue", + "sheet": "background_colors", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "read": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_green", + "sheet": "background_colors", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "read": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_custom", + "sheet": "background_colors", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "bg_red": { + "read": { + "passed": true, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - red" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "read": { + "passed": true, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "bg_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - blue" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "bg_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "read": { + "passed": true, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "bg_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - green" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "bg_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "read": { + "passed": true, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "bg_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - custom (#8B4513)" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "bg_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "bg_red": { + "read": { + "passed": true, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - red" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "read": { + "passed": true, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "bg_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - blue" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "bg_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "read": { + "passed": true, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "bg_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - green" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "bg_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "read": { + "passed": true, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "bg_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - custom (#8B4513)" + }, + "write": { + "passed": true, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "bg_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "bg_red": { + "read": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_red", + "sheet": "background_colors", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - red" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_red", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "read": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_blue", + "sheet": "background_colors", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - blue" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_blue", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "read": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_green", + "sheet": "background_colors", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - green" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_green", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "read": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_custom", + "sheet": "background_colors", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_custom", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "background_colors", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "bg_red": { + "read": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_red", + "sheet": "background_colors", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - red" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_red", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "read": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_blue", + "sheet": "background_colors", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - blue" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_blue", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "read": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_green", + "sheet": "background_colors", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - green" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_green", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "read": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_custom", + "sheet": "background_colors", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_custom", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "xlwt", + "scores": { + "read": null, + "write": 1 + }, + "test_cases": { + "bg_red": { + "write": { + "passed": true, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "write": { + "passed": true, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "bg_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "write": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "bg_color": "#008000" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_green", + "sheet": "background_colors", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={'bg_color': '#008000'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "write": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "bg_color": "#993300" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_custom", + "sheet": "background_colors", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={'bg_color': '#993300'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "bg_red": { + "read": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_red", + "sheet": "background_colors", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - red" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_red", + "sheet": "background_colors", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "read": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_blue", + "sheet": "background_colors", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - blue" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_blue", + "sheet": "background_colors", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "read": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_green", + "sheet": "background_colors", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - green" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_green", + "sheet": "background_colors", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "read": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_custom", + "sheet": "background_colors", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_custom", + "sheet": "background_colors", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "bg_red": { + "write": { + "passed": true, + "expected": { + "bg_color": "#FF0000" + }, + "actual": { + "bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "write": { + "passed": true, + "expected": { + "bg_color": "#0000FF" + }, + "actual": { + "bg_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "write": { + "passed": true, + "expected": { + "bg_color": "#00FF00" + }, + "actual": { + "bg_color": "#00FF00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "write": { + "passed": true, + "expected": { + "bg_color": "#8B4513" + }, + "actual": { + "bg_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "bg_red": { + "read": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_red", + "sheet": "background_colors", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "read": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_blue", + "sheet": "background_colors", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "read": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_green", + "sheet": "background_colors", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "read": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_custom", + "sheet": "background_colors", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "bg_red": { + "read": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_red", + "sheet": "background_colors", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "read": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_blue", + "sheet": "background_colors", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "read": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_green", + "sheet": "background_colors", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "read": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_custom", + "sheet": "background_colors", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "background_colors", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "bg_red": { + "read": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_red", + "sheet": "background_colors", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - red" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_red", + "sheet": "background_colors", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - red" + } + }, + "bg_blue": { + "read": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_blue", + "sheet": "background_colors", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - blue" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_blue", + "sheet": "background_colors", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - blue" + } + }, + "bg_green": { + "read": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_green", + "sheet": "background_colors", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - green" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#00FF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_green", + "sheet": "background_colors", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#00FF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - green" + } + }, + "bg_custom": { + "read": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "read", + "test_case_id": "bg_custom", + "sheet": "background_colors", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "bg_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "background_colors", + "operation": "write", + "test_case_id": "bg_custom", + "sheet": "background_colors", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'bg_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Background - custom (#8B4513)" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "numfmt_currency": { + "read": { + "passed": true, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "$#,##0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - currency" + }, + "write": { + "passed": true, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "$#,##0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "read": { + "passed": true, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "0.00%" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - percent" + }, + "write": { + "passed": true, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "0.00%" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "read": { + "passed": true, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "yyyy-mm-dd" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - date" + }, + "write": { + "passed": true, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "yyyy-mm-dd" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "read": { + "passed": true, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "0.00E+00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - scientific" + }, + "write": { + "passed": true, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "0.00E+00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "read": { + "passed": true, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "\"USD\" 0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - custom text" + }, + "write": { + "passed": true, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "\"USD\" 0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "numfmt_currency": { + "write": { + "passed": true, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "$#,##0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "write": { + "passed": true, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "0.00%" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "write": { + "passed": true, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "yyyy-mm-dd" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "write": { + "passed": true, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "0.00E+00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "write": { + "passed": true, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "\"USD\" 0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "numfmt_currency": { + "read": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_currency", + "sheet": "number_formats", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_percent", + "sheet": "number_formats", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "read": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_date", + "sheet": "number_formats", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_scientific", + "sheet": "number_formats", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "read": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_custom_text", + "sheet": "number_formats", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '\"USD\" 0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "numfmt_currency": { + "read": { + "passed": true, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "$#,##0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - currency" + }, + "write": { + "passed": true, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "$#,##0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "read": { + "passed": true, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "0.00%" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - percent" + }, + "write": { + "passed": true, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "0.00%" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "read": { + "passed": true, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "yyyy-mm-dd" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - date" + }, + "write": { + "passed": true, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "yyyy-mm-dd" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "read": { + "passed": true, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "0.00E+00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - scientific" + }, + "write": { + "passed": true, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "0.00E+00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "read": { + "passed": true, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "\"USD\" 0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - custom text" + }, + "write": { + "passed": true, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "\"USD\" 0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "numfmt_currency": { + "read": { + "passed": true, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "$#,##0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - currency" + }, + "write": { + "passed": true, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "$#,##0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "read": { + "passed": true, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "0.00%" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - percent" + }, + "write": { + "passed": true, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "0.00%" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "read": { + "passed": true, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "yyyy-mm-dd" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - date" + }, + "write": { + "passed": true, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "yyyy-mm-dd" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "read": { + "passed": true, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "0.00E+00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - scientific" + }, + "write": { + "passed": true, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "0.00E+00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "read": { + "passed": true, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "\"USD\" 0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - custom text" + }, + "write": { + "passed": true, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "\"USD\" 0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "numfmt_currency": { + "read": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_currency", + "sheet": "number_formats", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - currency" + }, + "write": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_currency", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_percent", + "sheet": "number_formats", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - percent" + }, + "write": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_percent", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "read": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_date", + "sheet": "number_formats", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - date" + }, + "write": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_date", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_scientific", + "sheet": "number_formats", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + }, + "write": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_scientific", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "read": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_custom_text", + "sheet": "number_formats", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '\"USD\" 0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + }, + "write": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_custom_text", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "number_formats", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "numfmt_currency": { + "read": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_currency", + "sheet": "number_formats", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - currency" + }, + "write": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_currency", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_percent", + "sheet": "number_formats", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - percent" + }, + "write": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_percent", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "read": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_date", + "sheet": "number_formats", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - date" + }, + "write": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_date", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_scientific", + "sheet": "number_formats", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + }, + "write": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_scientific", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "read": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_custom_text", + "sheet": "number_formats", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '\"USD\" 0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + }, + "write": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_custom_text", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "xlwt", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "numfmt_currency": { + "write": { + "passed": true, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "$#,##0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "write": { + "passed": true, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "0.00%" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "write": { + "passed": true, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "yyyy-mm-dd" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "write": { + "passed": true, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "0.00E+00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "write": { + "passed": true, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "\"USD\" 0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "numfmt_currency": { + "read": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_currency", + "sheet": "number_formats", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - currency" + }, + "write": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "General" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_currency", + "sheet": "number_formats", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={'number_format': 'General'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_percent", + "sheet": "number_formats", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - percent" + }, + "write": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "General" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_percent", + "sheet": "number_formats", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={'number_format': 'General'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "read": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_date", + "sheet": "number_formats", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - date" + }, + "write": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "General" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_date", + "sheet": "number_formats", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={'number_format': 'General'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_scientific", + "sheet": "number_formats", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + }, + "write": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "General" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_scientific", + "sheet": "number_formats", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={'number_format': 'General'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "read": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_custom_text", + "sheet": "number_formats", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '\"USD\" 0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + }, + "write": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "General" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_custom_text", + "sheet": "number_formats", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '\"USD\" 0.00'}, actual={'number_format': 'General'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "numfmt_currency": { + "write": { + "passed": true, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "$#,##0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "write": { + "passed": true, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "0.00%" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "write": { + "passed": true, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "yyyy-mm-dd" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "write": { + "passed": true, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "0.00E+00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "write": { + "passed": true, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "\"USD\" 0.00" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "numfmt_currency": { + "read": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_currency", + "sheet": "number_formats", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_percent", + "sheet": "number_formats", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "read": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_date", + "sheet": "number_formats", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_scientific", + "sheet": "number_formats", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "read": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_custom_text", + "sheet": "number_formats", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '\"USD\" 0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "numfmt_currency": { + "read": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_currency", + "sheet": "number_formats", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_percent", + "sheet": "number_formats", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "read": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_date", + "sheet": "number_formats", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_scientific", + "sheet": "number_formats", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "read": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_custom_text", + "sheet": "number_formats", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '\"USD\" 0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "number_formats", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "numfmt_currency": { + "read": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_currency", + "sheet": "number_formats", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - currency" + }, + "write": { + "passed": false, + "expected": { + "number_format": "$#,##0.00" + }, + "actual": { + "number_format": "General" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_currency", + "sheet": "number_formats", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '$#,##0.00'}, actual={'number_format': 'General'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - currency" + } + }, + "numfmt_percent": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_percent", + "sheet": "number_formats", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - percent" + }, + "write": { + "passed": false, + "expected": { + "number_format": "0.00%" + }, + "actual": { + "number_format": "General" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_percent", + "sheet": "number_formats", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00%'}, actual={'number_format': 'General'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - percent" + } + }, + "numfmt_date": { + "read": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_date", + "sheet": "number_formats", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - date" + }, + "write": { + "passed": false, + "expected": { + "number_format": "yyyy-mm-dd" + }, + "actual": { + "number_format": "General" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_date", + "sheet": "number_formats", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': 'yyyy-mm-dd'}, actual={'number_format': 'General'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - date" + } + }, + "numfmt_scientific": { + "read": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_scientific", + "sheet": "number_formats", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + }, + "write": { + "passed": false, + "expected": { + "number_format": "0.00E+00" + }, + "actual": { + "number_format": "General" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_scientific", + "sheet": "number_formats", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '0.00E+00'}, actual={'number_format': 'General'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - scientific" + } + }, + "numfmt_custom_text": { + "read": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "read", + "test_case_id": "numfmt_custom_text", + "sheet": "number_formats", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '\"USD\" 0.00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + }, + "write": { + "passed": false, + "expected": { + "number_format": "\"USD\" 0.00" + }, + "actual": { + "number_format": "General" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "number_formats", + "operation": "write", + "test_case_id": "numfmt_custom_text", + "sheet": "number_formats", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'number_format': '\"USD\" 0.00'}, actual={'number_format': 'General'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Format - custom text" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "h_left": { + "read": { + "passed": true, + "expected": { + "h_align": "left" + }, + "actual": { + "h_align": "left" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - left" + }, + "write": { + "passed": true, + "expected": { + "h_align": "left" + }, + "actual": { + "h_align": "left" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "read": { + "passed": true, + "expected": { + "h_align": "center" + }, + "actual": { + "h_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": true, + "expected": { + "h_align": "center" + }, + "actual": { + "h_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "read": { + "passed": true, + "expected": { + "h_align": "right" + }, + "actual": { + "h_align": "right" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - right" + }, + "write": { + "passed": true, + "expected": { + "h_align": "right" + }, + "actual": { + "h_align": "right" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "read": { + "passed": true, + "expected": { + "v_align": "top" + }, + "actual": { + "v_align": "top" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - top" + }, + "write": { + "passed": true, + "expected": { + "v_align": "top" + }, + "actual": { + "v_align": "top" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "read": { + "passed": true, + "expected": { + "v_align": "center" + }, + "actual": { + "v_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": true, + "expected": { + "v_align": "center" + }, + "actual": { + "v_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "read": { + "passed": true, + "expected": { + "v_align": "bottom" + }, + "actual": { + "v_align": "bottom" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - bottom" + }, + "write": { + "passed": true, + "expected": { + "v_align": "bottom" + }, + "actual": { + "v_align": "bottom" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "read": { + "passed": true, + "expected": { + "wrap": true + }, + "actual": { + "wrap": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - wrap text" + }, + "write": { + "passed": true, + "expected": { + "wrap": true + }, + "actual": { + "wrap": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "read": { + "passed": true, + "expected": { + "rotation": 45 + }, + "actual": { + "rotation": 45 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - rotation 45" + }, + "write": { + "passed": true, + "expected": { + "rotation": 45 + }, + "actual": { + "rotation": 45 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "read": { + "passed": true, + "expected": { + "indent": 2 + }, + "actual": { + "indent": 2.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - indent 2" + }, + "write": { + "passed": true, + "expected": { + "indent": 2 + }, + "actual": { + "indent": 2.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 1 + }, + "test_cases": { + "h_left": { + "write": { + "passed": true, + "expected": { + "h_align": "left" + }, + "actual": { + "h_align": "left" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "write": { + "passed": true, + "expected": { + "h_align": "center" + }, + "actual": { + "h_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "write": { + "passed": true, + "expected": { + "h_align": "right" + }, + "actual": { + "h_align": "right" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "write": { + "passed": true, + "expected": { + "v_align": "top" + }, + "actual": { + "v_align": "top" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "write": { + "passed": true, + "expected": { + "v_align": "center" + }, + "actual": { + "v_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "write": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "write": { + "passed": true, + "expected": { + "wrap": true + }, + "actual": { + "wrap": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "write": { + "passed": true, + "expected": { + "rotation": 45 + }, + "actual": { + "rotation": 45 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "write": { + "passed": true, + "expected": { + "indent": 2 + }, + "actual": { + "h_align": "left", + "indent": 2.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "h_left": { + "read": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_left", + "sheet": "alignment", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'left'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "read": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_center", + "sheet": "alignment", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "read": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_right", + "sheet": "alignment", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'right'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "read": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_top", + "sheet": "alignment", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'top'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "read": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_center", + "sheet": "alignment", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "read": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "read": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "wrap_text", + "sheet": "alignment", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'wrap': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "read": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "rotation_45", + "sheet": "alignment", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'rotation': 45}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "read": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "indent_2", + "sheet": "alignment", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'indent': 2}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": "Known limitation: python-calamine alignment read is limited because its API does not expose style/alignment metadata." + }, + { + "feature": "alignment", + "library": "aspose-cells-foss", + "scores": { + "read": 1, + "write": 1 + }, + "test_cases": { + "h_left": { + "read": { + "passed": true, + "expected": { + "h_align": "left" + }, + "actual": { + "h_align": "left" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - left" + }, + "write": { + "passed": true, + "expected": { + "h_align": "left" + }, + "actual": { + "h_align": "left" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "read": { + "passed": true, + "expected": { + "h_align": "center" + }, + "actual": { + "h_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": true, + "expected": { + "h_align": "center" + }, + "actual": { + "h_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "read": { + "passed": true, + "expected": { + "h_align": "right" + }, + "actual": { + "h_align": "right" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - right" + }, + "write": { + "passed": true, + "expected": { + "h_align": "right" + }, + "actual": { + "h_align": "right" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "read": { + "passed": true, + "expected": { + "v_align": "top" + }, + "actual": { + "v_align": "top" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - top" + }, + "write": { + "passed": true, + "expected": { + "v_align": "top" + }, + "actual": { + "v_align": "top" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "read": { + "passed": true, + "expected": { + "v_align": "center" + }, + "actual": { + "v_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": true, + "expected": { + "v_align": "center" + }, + "actual": { + "v_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "read": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + }, + "write": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "read": { + "passed": true, + "expected": { + "wrap": true + }, + "actual": { + "wrap": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - wrap text" + }, + "write": { + "passed": true, + "expected": { + "wrap": true + }, + "actual": { + "wrap": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "read": { + "passed": true, + "expected": { + "rotation": 45 + }, + "actual": { + "rotation": 45 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - rotation 45" + }, + "write": { + "passed": true, + "expected": { + "rotation": 45 + }, + "actual": { + "rotation": 45 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "read": { + "passed": true, + "expected": { + "indent": 2 + }, + "actual": { + "indent": 2 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - indent 2" + }, + "write": { + "passed": true, + "expected": { + "indent": 2 + }, + "actual": { + "indent": 2.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "h_left": { + "read": { + "passed": true, + "expected": { + "h_align": "left" + }, + "actual": { + "h_align": "left" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - left" + }, + "write": { + "passed": true, + "expected": { + "h_align": "left" + }, + "actual": { + "h_align": "left" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "read": { + "passed": true, + "expected": { + "h_align": "center" + }, + "actual": { + "h_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": true, + "expected": { + "h_align": "center" + }, + "actual": { + "h_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "read": { + "passed": true, + "expected": { + "h_align": "right" + }, + "actual": { + "h_align": "right" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - right" + }, + "write": { + "passed": true, + "expected": { + "h_align": "right" + }, + "actual": { + "h_align": "right" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "read": { + "passed": true, + "expected": { + "v_align": "top" + }, + "actual": { + "v_align": "top" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - top" + }, + "write": { + "passed": true, + "expected": { + "v_align": "top" + }, + "actual": { + "v_align": "top" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "read": { + "passed": true, + "expected": { + "v_align": "center" + }, + "actual": { + "v_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": true, + "expected": { + "v_align": "center" + }, + "actual": { + "v_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "read": { + "passed": true, + "expected": { + "v_align": "bottom" + }, + "actual": { + "v_align": "bottom" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - bottom" + }, + "write": { + "passed": true, + "expected": { + "v_align": "bottom" + }, + "actual": { + "v_align": "bottom" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "read": { + "passed": true, + "expected": { + "wrap": true + }, + "actual": { + "wrap": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - wrap text" + }, + "write": { + "passed": true, + "expected": { + "wrap": true + }, + "actual": { + "wrap": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "read": { + "passed": true, + "expected": { + "rotation": 45 + }, + "actual": { + "rotation": 45 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - rotation 45" + }, + "write": { + "passed": true, + "expected": { + "rotation": 45 + }, + "actual": { + "rotation": 45 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "read": { + "passed": true, + "expected": { + "indent": 2 + }, + "actual": { + "indent": 2 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - indent 2" + }, + "write": { + "passed": true, + "expected": { + "indent": 2 + }, + "actual": { + "indent": 2.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "h_left": { + "read": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_left", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Align - left" + }, + "write": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_left", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "read": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_center", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_center", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "read": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_right", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Align - right" + }, + "write": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_right", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "read": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_top", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Align - top" + }, + "write": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_top", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "read": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_center", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_center", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "read": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_bottom", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Align - bottom" + }, + "write": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_bottom", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "read": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "wrap_text", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Align - wrap text" + }, + "write": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "wrap_text", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "read": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "rotation_45", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Align - rotation 45" + }, + "write": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "rotation_45", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "read": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "indent_2", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Align - indent 2" + }, + "write": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": { + "error": "pylightxl does not support write_cell_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "indent_2", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": "Known limitation: pylightxl alignment write is a no-op because the library does not support formatting writes." + }, + { + "feature": "alignment", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "alignment", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "h_left": { + "read": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_left", + "sheet": "alignment", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'left'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - left" + }, + "write": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_left", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "read": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_center", + "sheet": "alignment", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_center", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "read": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_right", + "sheet": "alignment", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'right'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - right" + }, + "write": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_right", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "read": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_top", + "sheet": "alignment", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'top'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - top" + }, + "write": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_top", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "read": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_center", + "sheet": "alignment", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_center", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "read": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + }, + "write": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_bottom", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "read": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "wrap_text", + "sheet": "alignment", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'wrap': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - wrap text" + }, + "write": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "wrap_text", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "read": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "rotation_45", + "sheet": "alignment", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'rotation': 45}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - rotation 45" + }, + "write": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "rotation_45", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "read": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "indent_2", + "sheet": "alignment", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'indent': 2}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - indent 2" + }, + "write": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": { + "error": "pyexcel does not support write_cell_format: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "indent_2", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_format: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "xlwt", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "h_left": { + "write": { + "passed": true, + "expected": { + "h_align": "left" + }, + "actual": { + "h_align": "left", + "v_align": "bottom" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "write": { + "passed": true, + "expected": { + "h_align": "center" + }, + "actual": { + "h_align": "center", + "v_align": "bottom" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "write": { + "passed": true, + "expected": { + "h_align": "right" + }, + "actual": { + "h_align": "right", + "v_align": "bottom" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "write": { + "passed": true, + "expected": { + "v_align": "top" + }, + "actual": { + "v_align": "top" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "write": { + "passed": true, + "expected": { + "v_align": "center" + }, + "actual": { + "v_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "write": { + "passed": true, + "expected": { + "v_align": "bottom" + }, + "actual": { + "v_align": "bottom" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "write": { + "passed": true, + "expected": { + "wrap": true + }, + "actual": { + "v_align": "bottom", + "wrap": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "write": { + "passed": true, + "expected": { + "rotation": 45 + }, + "actual": { + "v_align": "bottom", + "rotation": 45 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "write": { + "passed": true, + "expected": { + "indent": 2 + }, + "actual": { + "v_align": "bottom", + "indent": 2 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "h_left": { + "read": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_left", + "sheet": "alignment", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'left'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - left" + }, + "write": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_left", + "sheet": "alignment", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'left'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "read": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_center", + "sheet": "alignment", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_center", + "sheet": "alignment", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "read": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_right", + "sheet": "alignment", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'right'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - right" + }, + "write": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_right", + "sheet": "alignment", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'right'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "read": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_top", + "sheet": "alignment", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'top'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - top" + }, + "write": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_top", + "sheet": "alignment", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'top'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "read": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_center", + "sheet": "alignment", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_center", + "sheet": "alignment", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "read": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + }, + "write": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "read": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "wrap_text", + "sheet": "alignment", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'wrap': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - wrap text" + }, + "write": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "wrap_text", + "sheet": "alignment", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'wrap': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "read": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "rotation_45", + "sheet": "alignment", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'rotation': 45}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - rotation 45" + }, + "write": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "rotation_45", + "sheet": "alignment", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'rotation': 45}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "read": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "indent_2", + "sheet": "alignment", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'indent': 2}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - indent 2" + }, + "write": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "indent_2", + "sheet": "alignment", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'indent': 2}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 1 + }, + "test_cases": { + "h_left": { + "write": { + "passed": true, + "expected": { + "h_align": "left" + }, + "actual": { + "h_align": "left" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "write": { + "passed": true, + "expected": { + "h_align": "center" + }, + "actual": { + "h_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "write": { + "passed": true, + "expected": { + "h_align": "right" + }, + "actual": { + "h_align": "right" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "write": { + "passed": true, + "expected": { + "v_align": "top" + }, + "actual": { + "v_align": "top" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "write": { + "passed": true, + "expected": { + "v_align": "center" + }, + "actual": { + "v_align": "center" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "write": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "write": { + "passed": true, + "expected": { + "wrap": true + }, + "actual": { + "wrap": true + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "write": { + "passed": true, + "expected": { + "rotation": 45 + }, + "actual": { + "rotation": 45 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "write": { + "passed": true, + "expected": { + "indent": 2 + }, + "actual": { + "h_align": "left", + "indent": 2.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "h_left": { + "read": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_left", + "sheet": "alignment", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'left'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "read": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_center", + "sheet": "alignment", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "read": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_right", + "sheet": "alignment", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'right'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "read": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_top", + "sheet": "alignment", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'top'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "read": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_center", + "sheet": "alignment", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "read": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "read": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "wrap_text", + "sheet": "alignment", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'wrap': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "read": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "rotation_45", + "sheet": "alignment", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'rotation': 45}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "read": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "indent_2", + "sheet": "alignment", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'indent': 2}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "h_left": { + "read": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_left", + "sheet": "alignment", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'left'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "read": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_center", + "sheet": "alignment", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "read": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_right", + "sheet": "alignment", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'right'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "read": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_top", + "sheet": "alignment", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'top'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "read": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_center", + "sheet": "alignment", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "read": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "read": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "wrap_text", + "sheet": "alignment", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'wrap': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "read": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "rotation_45", + "sheet": "alignment", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'rotation': 45}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "read": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "indent_2", + "sheet": "alignment", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'indent': 2}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "alignment", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "h_left": { + "read": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_left", + "sheet": "alignment", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'left'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - left" + }, + "write": { + "passed": false, + "expected": { + "h_align": "left" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_left", + "sheet": "alignment", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'left'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - left" + } + }, + "h_center": { + "read": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_center", + "sheet": "alignment", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": false, + "expected": { + "h_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_center", + "sheet": "alignment", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "h_right": { + "read": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "h_right", + "sheet": "alignment", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'right'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - right" + }, + "write": { + "passed": false, + "expected": { + "h_align": "right" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "h_right", + "sheet": "alignment", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'h_align': 'right'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - right" + } + }, + "v_top": { + "read": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_top", + "sheet": "alignment", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'top'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - top" + }, + "write": { + "passed": false, + "expected": { + "v_align": "top" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_top", + "sheet": "alignment", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'top'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - top" + } + }, + "v_center": { + "read": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_center", + "sheet": "alignment", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + }, + "write": { + "passed": false, + "expected": { + "v_align": "center" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_center", + "sheet": "alignment", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'center'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - center" + } + }, + "v_bottom": { + "read": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + }, + "write": { + "passed": false, + "expected": { + "v_align": "bottom" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "v_bottom", + "sheet": "alignment", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'v_align': 'bottom'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - bottom" + } + }, + "wrap_text": { + "read": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "wrap_text", + "sheet": "alignment", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'wrap': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - wrap text" + }, + "write": { + "passed": false, + "expected": { + "wrap": true + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "wrap_text", + "sheet": "alignment", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'wrap': True}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - wrap text" + } + }, + "rotation_45": { + "read": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "rotation_45", + "sheet": "alignment", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'rotation': 45}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - rotation 45" + }, + "write": { + "passed": false, + "expected": { + "rotation": 45 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "rotation_45", + "sheet": "alignment", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'rotation': 45}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - rotation 45" + } + }, + "indent_2": { + "read": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "read", + "test_case_id": "indent_2", + "sheet": "alignment", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'indent': 2}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - indent 2" + }, + "write": { + "passed": false, + "expected": { + "indent": 2 + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "alignment", + "operation": "write", + "test_case_id": "indent_2", + "sheet": "alignment", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'indent': 2}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Align - indent 2" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "thin_all": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "border_style": "thin", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thin all edges" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "border_style": "thin", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "read": { + "passed": true, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "border_style": "medium", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - medium all edges" + }, + "write": { + "passed": true, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "border_style": "medium", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "read": { + "passed": true, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "border_style": "thick", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thick all edges" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "border_style": "thick", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "read": { + "passed": true, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "border_style": "double", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - double line" + }, + "write": { + "passed": true, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "border_style": "double", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "read": { + "passed": true, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dashed" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "read": { + "passed": true, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "border_style": "dotted", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dotted" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "border_style": "dotted", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "read": { + "passed": true, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "read": { + "passed": true, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot-dot" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "read": { + "passed": true, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "border_top": "thin", + "border_top_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - top only" + }, + "write": { + "passed": true, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "border_top": "thin", + "border_top_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "read": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "border_bottom": "thin", + "border_bottom_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - bottom only" + }, + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "border_bottom": "thin", + "border_bottom_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "read": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "border_left": "thin", + "border_left_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - left only" + }, + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "border_left": "thin", + "border_left_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "read": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "border_right": "thin", + "border_right_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - right only" + }, + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "border_right": "thin", + "border_right_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "read": { + "passed": true, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "border_diagonal_up": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal up" + }, + "write": { + "passed": true, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "border_diagonal_up": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "read": { + "passed": true, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal down" + }, + "write": { + "passed": true, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "read": { + "passed": true, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal both" + }, + "write": { + "passed": true, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - red color" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - blue color" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "read": { + "passed": true, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed styles per edge" + }, + "write": { + "passed": true, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "read": { + "passed": true, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00", + "border_style": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed colors per edge" + }, + "write": { + "passed": true, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00", + "border_style": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "thin_all": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "border_style": "thin", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "write": { + "passed": true, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "border_style": "medium", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "write": { + "passed": true, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "border_style": "thick", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "write": { + "passed": true, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "border_style": "double", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "write": { + "passed": true, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "write": { + "passed": true, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "border_style": "dotted", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "write": { + "passed": true, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "write": { + "passed": true, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "write": { + "passed": true, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "border_top": "thin", + "border_top_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "border_bottom": "thin", + "border_bottom_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "border_left": "thin", + "border_left_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "border_right": "thin", + "border_right_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "write": { + "passed": true, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "border_diagonal_up": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "write": { + "passed": true, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "write": { + "passed": true, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "write": { + "passed": true, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "write": { + "passed": true, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00", + "border_style": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "thin_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thin_all", + "sheet": "borders", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "read": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "medium_all", + "sheet": "borders", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thick_all", + "sheet": "borders", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "read": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "double", + "sheet": "borders", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "read": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dashed", + "sheet": "borders", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "read": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dotted", + "sheet": "borders", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot", + "sheet": "borders", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot_dot", + "sheet": "borders", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "read": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "top_only", + "sheet": "borders", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "bottom_only", + "sheet": "borders", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "left_only", + "sheet": "borders", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "right_only", + "sheet": "borders", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "read": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_both", + "sheet": "borders", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_red", + "sheet": "borders", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "borders", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "borders", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "read": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_styles", + "sheet": "borders", + "cell": "B20" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "read": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_colors", + "sheet": "borders", + "cell": "B21" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "aspose-cells-foss", + "scores": { + "read": 1, + "write": 1 + }, + "test_cases": { + "thin_all": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "border_style": "thin", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thin all edges" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "border_style": "thin", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "read": { + "passed": true, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "border_style": "medium", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - medium all edges" + }, + "write": { + "passed": true, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "border_style": "medium", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "read": { + "passed": true, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "border_style": "thick", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thick all edges" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "border_style": "thick", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "read": { + "passed": true, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "border_style": "double", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - double line" + }, + "write": { + "passed": true, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "border_style": "double", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "read": { + "passed": true, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dashed" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "read": { + "passed": true, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "border_style": "dotted", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dotted" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "border_style": "dotted", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "read": { + "passed": true, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "read": { + "passed": true, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot-dot" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "read": { + "passed": true, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "border_top": "thin", + "border_top_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - top only" + }, + "write": { + "passed": true, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "border_top": "thin", + "border_top_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "read": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "border_bottom": "thin", + "border_bottom_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - bottom only" + }, + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "border_bottom": "thin", + "border_bottom_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "read": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "border_left": "thin", + "border_left_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - left only" + }, + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "border_left": "thin", + "border_left_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "read": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "border_right": "thin", + "border_right_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - right only" + }, + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "border_right": "thin", + "border_right_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "read": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_both", + "sheet": "borders", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal both" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_both", + "sheet": "borders", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - red color" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - blue color" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "read": { + "passed": true, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed styles per edge" + }, + "write": { + "passed": true, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "read": { + "passed": true, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00", + "border_style": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed colors per edge" + }, + "write": { + "passed": true, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00", + "border_style": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "thin_all": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "border_style": "thin", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thin all edges" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "border_style": "thin", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "read": { + "passed": true, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "border_style": "medium", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - medium all edges" + }, + "write": { + "passed": true, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "border_style": "medium", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "read": { + "passed": true, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "border_style": "thick", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thick all edges" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "border_style": "thick", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "read": { + "passed": true, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "border_style": "double", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - double line" + }, + "write": { + "passed": true, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "border_style": "double", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "read": { + "passed": true, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dashed" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "read": { + "passed": true, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "border_style": "dotted", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dotted" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "border_style": "dotted", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "read": { + "passed": true, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "read": { + "passed": true, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot-dot" + }, + "write": { + "passed": true, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "read": { + "passed": true, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "border_top": "thin", + "border_top_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - top only" + }, + "write": { + "passed": true, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "border_top": "thin", + "border_top_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "read": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "border_bottom": "thin", + "border_bottom_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - bottom only" + }, + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "border_bottom": "thin", + "border_bottom_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "read": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "border_left": "thin", + "border_left_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - left only" + }, + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "border_left": "thin", + "border_left_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "read": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "border_right": "thin", + "border_right_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - right only" + }, + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "border_right": "thin", + "border_right_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "read": { + "passed": true, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "border_diagonal_up": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal up" + }, + "write": { + "passed": true, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "border_diagonal_up": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "read": { + "passed": true, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal down" + }, + "write": { + "passed": true, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "read": { + "passed": true, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal both" + }, + "write": { + "passed": true, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - red color" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - blue color" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "read": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + }, + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "read": { + "passed": true, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed styles per edge" + }, + "write": { + "passed": true, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "read": { + "passed": true, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00", + "border_style": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed colors per edge" + }, + "write": { + "passed": true, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00", + "border_style": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "thin_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thin_all", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "thin_all", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "read": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "medium_all", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "medium_all", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thick_all", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "thick_all", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "read": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "double", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - double line" + }, + "write": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "double", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "read": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dashed", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dashed", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "read": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dotted", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dotted", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dash_dot", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot_dot", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dash_dot_dot", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "read": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "top_only", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Border - top only" + }, + "write": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "top_only", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "bottom_only", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Border - bottom only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "bottom_only", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "left_only", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Border - left only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "left_only", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "right_only", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Border - right only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "right_only", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_up", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Border - diagonal up" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_up", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "read": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_down", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Border - diagonal down" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_down", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_both", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Border - diagonal both" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_both", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_red", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - red color" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_red", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_blue", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_blue", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_custom", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_custom", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "read": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_styles", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + }, + "write": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_styles", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "read": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_colors", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + }, + "write": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "error": "pylightxl does not support write_cell_border: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_colors", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support write_cell_border: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "borders", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "thin_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thin_all", + "sheet": "borders", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "thin_all", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "read": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "medium_all", + "sheet": "borders", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "medium_all", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thick_all", + "sheet": "borders", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "thick_all", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "read": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "double", + "sheet": "borders", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - double line" + }, + "write": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "double", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "read": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dashed", + "sheet": "borders", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dashed", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "read": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dotted", + "sheet": "borders", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dotted", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot", + "sheet": "borders", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dash_dot", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot_dot", + "sheet": "borders", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dash_dot_dot", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "read": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "top_only", + "sheet": "borders", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - top only" + }, + "write": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "top_only", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "bottom_only", + "sheet": "borders", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - bottom only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "bottom_only", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "left_only", + "sheet": "borders", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - left only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "left_only", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "right_only", + "sheet": "borders", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - right only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "right_only", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_up", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "read": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_down", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_both", + "sheet": "borders", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal both" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_both", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_red", + "sheet": "borders", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - red color" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_red", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "borders", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_blue", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "borders", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_custom", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "read": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_styles", + "sheet": "borders", + "cell": "B20" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + }, + "write": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_styles", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "read": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_colors", + "sheet": "borders", + "cell": "B21" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + }, + "write": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "error": "pyexcel does not support write_cell_border: pyexcel exposes value-only cells" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_colors", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support write_cell_border: pyexcel exposes value-only cells", + "probable_cause": "pyexcel exposes value-only cells", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel exposes value-only cells", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "xlwt", + "scores": { + "read": null, + "write": 1 + }, + "test_cases": { + "thin_all": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "border_style": "thin", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "write": { + "passed": true, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "border_style": "medium", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "write": { + "passed": true, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "border_style": "thick", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "write": { + "passed": true, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "border_style": "double", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "write": { + "passed": true, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "write": { + "passed": true, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "border_style": "dotted", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "write": { + "passed": true, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "write": { + "passed": true, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "write": { + "passed": true, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "border_top": "thin", + "border_top_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "border_bottom": "thin", + "border_bottom_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "border_left": "thin", + "border_left_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "border_right": "thin", + "border_right_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "border_diagonal_down": "thin" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={'border_diagonal_down': 'thin'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "write": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_up": "thin" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={'border_diagonal_up': 'thin'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "write": { + "passed": true, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "border_style": "thin", + "border_color": "#993300" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_custom", + "sheet": "borders", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={'border_style': 'thin', 'border_color': '#993300'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "write": { + "passed": true, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "write": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "border_top_color": "#FF0000", + "border_bottom_color": "#008000", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00", + "border_style": "thin" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_colors", + "sheet": "borders", + "cell": "B21" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={'border_top_color': '#FF0000', 'border_bottom_color': '#008000', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00', 'border_style': 'thin'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "thin_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thin_all", + "sheet": "borders", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "thin_all", + "sheet": "borders", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "read": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "medium_all", + "sheet": "borders", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "medium_all", + "sheet": "borders", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thick_all", + "sheet": "borders", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "thick_all", + "sheet": "borders", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "read": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "double", + "sheet": "borders", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - double line" + }, + "write": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "double", + "sheet": "borders", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "read": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dashed", + "sheet": "borders", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dashed", + "sheet": "borders", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "read": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dotted", + "sheet": "borders", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dotted", + "sheet": "borders", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot", + "sheet": "borders", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dash_dot", + "sheet": "borders", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot_dot", + "sheet": "borders", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dash_dot_dot", + "sheet": "borders", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "read": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "top_only", + "sheet": "borders", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - top only" + }, + "write": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "top_only", + "sheet": "borders", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "bottom_only", + "sheet": "borders", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - bottom only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "bottom_only", + "sheet": "borders", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "left_only", + "sheet": "borders", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - left only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "left_only", + "sheet": "borders", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "right_only", + "sheet": "borders", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - right only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "right_only", + "sheet": "borders", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "read": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_both", + "sheet": "borders", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal both" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_both", + "sheet": "borders", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_red", + "sheet": "borders", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - red color" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_red", + "sheet": "borders", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "borders", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_blue", + "sheet": "borders", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "borders", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_custom", + "sheet": "borders", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "read": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_styles", + "sheet": "borders", + "cell": "B20" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + }, + "write": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_styles", + "sheet": "borders", + "cell": "B20" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "read": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_colors", + "sheet": "borders", + "cell": "B21" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + }, + "write": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_colors", + "sheet": "borders", + "cell": "B21" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "thin_all": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": { + "border_style": "thin", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "write": { + "passed": true, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": { + "border_style": "medium", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "write": { + "passed": true, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": { + "border_style": "thick", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "write": { + "passed": true, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": { + "border_style": "double", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "write": { + "passed": true, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "write": { + "passed": true, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": { + "border_style": "dotted", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "write": { + "passed": true, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "write": { + "passed": true, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "write": { + "passed": true, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": { + "border_top": "thin", + "border_top_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": { + "border_bottom": "thin", + "border_bottom_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": { + "border_left": "thin", + "border_left_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "write": { + "passed": true, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": { + "border_right": "thin", + "border_right_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "write": { + "passed": true, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": { + "border_diagonal_up": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "write": { + "passed": true, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "write": { + "passed": true, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "write": { + "passed": true, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "write": { + "passed": true, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed", + "border_color": "#000000" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "write": { + "passed": true, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00", + "border_style": "thin" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "thin_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thin_all", + "sheet": "borders", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "read": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "medium_all", + "sheet": "borders", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thick_all", + "sheet": "borders", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "read": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "double", + "sheet": "borders", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "read": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dashed", + "sheet": "borders", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "read": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dotted", + "sheet": "borders", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot", + "sheet": "borders", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot_dot", + "sheet": "borders", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "read": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "top_only", + "sheet": "borders", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "bottom_only", + "sheet": "borders", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "left_only", + "sheet": "borders", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "right_only", + "sheet": "borders", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "read": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_both", + "sheet": "borders", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_red", + "sheet": "borders", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "borders", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "borders", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "read": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_styles", + "sheet": "borders", + "cell": "B20" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "read": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_colors", + "sheet": "borders", + "cell": "B21" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "thin_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thin_all", + "sheet": "borders", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "read": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "medium_all", + "sheet": "borders", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thick_all", + "sheet": "borders", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "read": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "double", + "sheet": "borders", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "read": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dashed", + "sheet": "borders", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "read": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dotted", + "sheet": "borders", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot", + "sheet": "borders", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot_dot", + "sheet": "borders", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "read": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "top_only", + "sheet": "borders", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "bottom_only", + "sheet": "borders", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "left_only", + "sheet": "borders", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "right_only", + "sheet": "borders", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "read": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_both", + "sheet": "borders", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_red", + "sheet": "borders", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "borders", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "borders", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "read": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_styles", + "sheet": "borders", + "cell": "B20" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "read": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_colors", + "sheet": "borders", + "cell": "B21" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "borders", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "thin_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thin_all", + "sheet": "borders", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "thin_all", + "sheet": "borders", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thin all edges" + } + }, + "medium_all": { + "read": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "medium_all", + "sheet": "borders", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "medium", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "medium_all", + "sheet": "borders", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'medium', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - medium all edges" + } + }, + "thick_all": { + "read": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "thick_all", + "sheet": "borders", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thick", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "thick_all", + "sheet": "borders", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thick', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - thick all edges" + } + }, + "double": { + "read": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "double", + "sheet": "borders", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - double line" + }, + "write": { + "passed": false, + "expected": { + "border_style": "double", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "double", + "sheet": "borders", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'double', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - double line" + } + }, + "dashed": { + "read": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dashed", + "sheet": "borders", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashed", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dashed", + "sheet": "borders", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashed', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dashed" + } + }, + "dotted": { + "read": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dotted", + "sheet": "borders", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dotted", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dotted", + "sheet": "borders", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dotted', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dotted" + } + }, + "dash_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot", + "sheet": "borders", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dash_dot", + "sheet": "borders", + "cell": "B8" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot" + } + }, + "dash_dot_dot": { + "read": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "dash_dot_dot", + "sheet": "borders", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + }, + "write": { + "passed": false, + "expected": { + "border_style": "dashDotDot", + "border_color": "#000000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "dash_dot_dot", + "sheet": "borders", + "cell": "B9" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'dashDotDot', 'border_color': '#000000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - dash-dot-dot" + } + }, + "top_only": { + "read": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "top_only", + "sheet": "borders", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - top only" + }, + "write": { + "passed": false, + "expected": { + "border_top": "thin", + "border_bottom": null, + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "top_only", + "sheet": "borders", + "cell": "B10" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thin', 'border_bottom': None, 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - top only" + } + }, + "bottom_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "bottom_only", + "sheet": "borders", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - bottom only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": "thin", + "border_left": null, + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "bottom_only", + "sheet": "borders", + "cell": "B11" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': 'thin', 'border_left': None, 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - bottom only" + } + }, + "left_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "left_only", + "sheet": "borders", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - left only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": "thin", + "border_right": null + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "left_only", + "sheet": "borders", + "cell": "B12" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': 'thin', 'border_right': None}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - left only" + } + }, + "right_only": { + "read": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "right_only", + "sheet": "borders", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - right only" + }, + "write": { + "passed": false, + "expected": { + "border_top": null, + "border_bottom": null, + "border_left": null, + "border_right": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "right_only", + "sheet": "borders", + "cell": "B13" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': None, 'border_bottom': None, 'border_left': None, 'border_right': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - right only" + } + }, + "diagonal_up": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_up", + "sheet": "borders", + "cell": "B14" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal up" + } + }, + "diagonal_down": { + "read": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_down", + "sheet": "borders", + "cell": "B15" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal down" + } + }, + "diagonal_both": { + "read": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "diagonal_both", + "sheet": "borders", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal both" + }, + "write": { + "passed": false, + "expected": { + "border_diagonal_up": "thin", + "border_diagonal_down": "thin" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "diagonal_both", + "sheet": "borders", + "cell": "B16" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_diagonal_up': 'thin', 'border_diagonal_down': 'thin'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - diagonal both" + } + }, + "color_red": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_red", + "sheet": "borders", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - red color" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#FF0000" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_red", + "sheet": "borders", + "cell": "B17" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#FF0000'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - red color" + } + }, + "color_blue": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_blue", + "sheet": "borders", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#0000FF" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_blue", + "sheet": "borders", + "cell": "B18" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#0000FF'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - blue color" + } + }, + "color_custom": { + "read": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "color_custom", + "sheet": "borders", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + }, + "write": { + "passed": false, + "expected": { + "border_style": "thin", + "border_color": "#8B4513" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "color_custom", + "sheet": "borders", + "cell": "B19" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_style': 'thin', 'border_color': '#8B4513'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - custom color (#8B4513)" + } + }, + "mixed_styles": { + "read": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_styles", + "sheet": "borders", + "cell": "B20" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + }, + "write": { + "passed": false, + "expected": { + "border_top": "thick", + "border_bottom": "thin", + "border_left": "medium", + "border_right": "dashed" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_styles", + "sheet": "borders", + "cell": "B20" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top': 'thick', 'border_bottom': 'thin', 'border_left': 'medium', 'border_right': 'dashed'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Border - mixed styles per edge" + } + }, + "mixed_colors": { + "read": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "read", + "test_case_id": "mixed_colors", + "sheet": "borders", + "cell": "B21" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + }, + "write": { + "passed": false, + "expected": { + "border_top_color": "#FF0000", + "border_bottom_color": "#00FF00", + "border_left_color": "#0000FF", + "border_right_color": "#FFFF00" + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "borders", + "operation": "write", + "test_case_id": "mixed_colors", + "sheet": "borders", + "cell": "B21" + }, + "adapter_message": "Expected values did not match actual values: expected={'border_top_color': '#FF0000', 'border_bottom_color': '#00FF00', 'border_left_color': '#0000FF', 'border_right_color': '#FFFF00'}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Border - mixed colors per edge" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "row_height_30": { + "read": { + "passed": true, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": 30.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 30" + }, + "write": { + "passed": true, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": 30.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "read": { + "passed": true, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": 45.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 45" + }, + "write": { + "passed": true, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": 45.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "read": { + "passed": true, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 20.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - D = 20" + }, + "write": { + "passed": true, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 20.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "read": { + "passed": true, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - E = 8" + }, + "write": { + "passed": true, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "row_height_30": { + "write": { + "passed": true, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": 30.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "write": { + "passed": true, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": 45.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "write": { + "passed": true, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 20.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "write": { + "passed": true, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "row_height_30": { + "read": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "read": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "read": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_20", + "sheet": "dimensions", + "cell": "D4" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "read": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_8", + "sheet": "dimensions", + "cell": "E5" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "aspose-cells-foss", + "scores": { + "read": 1, + "write": 3 + }, + "test_cases": { + "row_height_30": { + "read": { + "passed": true, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": 30.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 30" + }, + "write": { + "passed": true, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": 30.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "read": { + "passed": true, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": 45.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 45" + }, + "write": { + "passed": true, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": 45.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "read": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 20.83203125 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_20", + "sheet": "dimensions", + "cell": "D4" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': 20.83203125}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - D = 20" + }, + "write": { + "passed": true, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 20.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "read": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 8.83203125 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_8", + "sheet": "dimensions", + "cell": "E5" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': 8.83203125}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - E = 8" + }, + "write": { + "passed": true, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "row_height_30": { + "read": { + "passed": true, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": 30.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 30" + }, + "write": { + "passed": true, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": 30.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "read": { + "passed": true, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": 45.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 45" + }, + "write": { + "passed": true, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": 45.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "read": { + "passed": true, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 20.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - D = 20" + }, + "write": { + "passed": true, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 20.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "read": { + "passed": true, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - E = 8" + }, + "write": { + "passed": true, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "row_height_30": { + "read": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + }, + "write": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "error": "pylightxl does not support set_row_height: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_30", + "sheet": null, + "cell": "B2" + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support set_row_height: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "read": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + }, + "write": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "error": "pylightxl does not support set_row_height: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_45", + "sheet": null, + "cell": "B3" + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support set_row_height: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "read": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_20", + "sheet": "dimensions", + "cell": "D4" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - D = 20" + }, + "write": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "error": "pylightxl does not support set_row_height: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "col_width_20", + "sheet": null, + "cell": "D4" + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support set_row_height: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "read": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_8", + "sheet": "dimensions", + "cell": "E5" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - E = 8" + }, + "write": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "error": "pylightxl does not support set_row_height: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "col_width_8", + "sheet": null, + "cell": "E5" + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support set_row_height: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "dimensions", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "row_height_30": { + "read": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + }, + "write": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "error": "pyexcel does not support set_row_height: pyexcel does not expose row dimension writing" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_30", + "sheet": null, + "cell": "B2" + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support set_row_height: pyexcel does not expose row dimension writing", + "probable_cause": "pyexcel does not expose row dimension writing", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose row dimension writing", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "read": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + }, + "write": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "error": "pyexcel does not support set_row_height: pyexcel does not expose row dimension writing" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_45", + "sheet": null, + "cell": "B3" + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support set_row_height: pyexcel does not expose row dimension writing", + "probable_cause": "pyexcel does not expose row dimension writing", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose row dimension writing", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "read": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_20", + "sheet": "dimensions", + "cell": "D4" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - D = 20" + }, + "write": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "error": "pyexcel does not support set_row_height: pyexcel does not expose row dimension writing" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "col_width_20", + "sheet": null, + "cell": "D4" + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support set_row_height: pyexcel does not expose row dimension writing", + "probable_cause": "pyexcel does not expose row dimension writing", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose row dimension writing", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "read": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_8", + "sheet": "dimensions", + "cell": "E5" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - E = 8" + }, + "write": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "error": "pyexcel does not support set_row_height: pyexcel does not expose row dimension writing" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "col_width_8", + "sheet": null, + "cell": "E5" + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support set_row_height: pyexcel does not expose row dimension writing", + "probable_cause": "pyexcel does not expose row dimension writing", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose row dimension writing", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "xlwt", + "scores": { + "read": null, + "write": 1 + }, + "test_cases": { + "row_height_30": { + "write": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "write": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "write": { + "passed": true, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 20.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "write": { + "passed": true, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "row_height_30": { + "read": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + }, + "write": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "read": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + }, + "write": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "read": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_20", + "sheet": "dimensions", + "cell": "D4" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - D = 20" + }, + "write": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 13.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "col_width_20", + "sheet": "dimensions", + "cell": "D4" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': 13.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "read": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_8", + "sheet": "dimensions", + "cell": "E5" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - E = 8" + }, + "write": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 13.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "col_width_8", + "sheet": "dimensions", + "cell": "E5" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': 13.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 1 + }, + "test_cases": { + "row_height_30": { + "write": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "write": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "write": { + "passed": true, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 20.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "write": { + "passed": true, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 8.0 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "row_height_30": { + "read": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "read": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "read": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_20", + "sheet": "dimensions", + "cell": "D4" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "read": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_8", + "sheet": "dimensions", + "cell": "E5" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "row_height_30": { + "read": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "read": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "read": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_20", + "sheet": "dimensions", + "cell": "D4" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "read": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_8", + "sheet": "dimensions", + "cell": "E5" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "dimensions", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "row_height_30": { + "read": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + }, + "write": { + "passed": false, + "expected": { + "row_height": 30 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_30", + "sheet": "dimensions", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 30}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 30" + } + }, + "row_height_45": { + "read": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + }, + "write": { + "passed": false, + "expected": { + "row_height": 45 + }, + "actual": { + "row_height": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "row_height_45", + "sheet": "dimensions", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'row_height': 45}, actual={'row_height': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Row height - 45" + } + }, + "col_width_20": { + "read": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_20", + "sheet": "dimensions", + "cell": "D4" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - D = 20" + }, + "write": { + "passed": false, + "expected": { + "column_width": 20 + }, + "actual": { + "column_width": 13.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "col_width_20", + "sheet": "dimensions", + "cell": "D4" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 20}, actual={'column_width': 13.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - D = 20" + } + }, + "col_width_8": { + "read": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "read", + "test_case_id": "col_width_8", + "sheet": "dimensions", + "cell": "E5" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - E = 8" + }, + "write": { + "passed": false, + "expected": { + "column_width": 8 + }, + "actual": { + "column_width": 13.0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "dimensions", + "operation": "write", + "test_case_id": "col_width_8", + "sheet": "dimensions", + "cell": "E5" + }, + "adapter_message": "Expected values did not match actual values: expected={'column_width': 8}, actual={'column_width': 13.0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Column width - E = 8" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "read": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + }, + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "python-calamine", + "scores": { + "read": 3, + "write": null + }, + "test_cases": { + "sheet_names": { + "read": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "read": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + }, + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "read": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + }, + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "pylightxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "read": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + }, + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "multiple_sheets", + "library": "pyexcel", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "read": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + }, + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "xlwt", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "pandas", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "read": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + }, + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "openpyxl-readonly", + "scores": { + "read": 3, + "write": null + }, + "test_cases": { + "sheet_names": { + "read": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "polars", + "scores": { + "read": 1, + "write": null + }, + "test_cases": { + "sheet_names": { + "read": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "read": { + "passed": false, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "multiple_sheets", + "operation": "read", + "test_case_id": "value_beta", + "sheet": "Beta", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'string', 'value': 'Beta'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "read": { + "passed": false, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "blank" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "multiple_sheets", + "operation": "read", + "test_case_id": "value_gamma", + "sheet": "Gamma", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'type': 'string', 'value': 'Gamma'}, actual={'type': 'blank'}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "multiple_sheets", + "library": "tablib", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "sheet_names": { + "read": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + }, + "write": { + "passed": true, + "expected": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "actual": { + "sheet_names": [ + "Alpha", + "Beta", + "Gamma" + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Sheet names" + } + }, + "value_alpha": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Alpha" + }, + "actual": { + "type": "string", + "value": "Alpha" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Alpha value" + } + }, + "value_beta": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Beta" + }, + "actual": { + "type": "string", + "value": "Beta" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Beta value" + } + }, + "value_gamma": { + "read": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + }, + "write": { + "passed": true, + "expected": { + "type": "string", + "value": "Gamma" + }, + "actual": { + "type": "string", + "value": "Gamma" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Gamma value" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "merge_horizontal": { + "read": { + "passed": true, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge horizontal B2:D2" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "read": { + "passed": true, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge vertical B3:B5" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "read": { + "passed": true, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with non-top-left value" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "read": { + "passed": true, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with top-left fill" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "merge_horizontal": { + "write": { + "passed": true, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "write": { + "passed": true, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "write": { + "passed": true, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "write": { + "passed": true, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "merge_horizontal": { + "read": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_horizontal", + "sheet": "merged_cells", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "read": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_vertical", + "sheet": "merged_cells", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "read": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_value_off_top_left", + "sheet": "merged_cells", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "read": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_top_left_fill", + "sheet": "merged_cells", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "merge_horizontal": { + "read": { + "passed": true, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge horizontal B2:D2" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "read": { + "passed": true, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge vertical B3:B5" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "read": { + "passed": true, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with non-top-left value" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "read": { + "passed": true, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with top-left fill" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "merge_horizontal": { + "read": { + "passed": true, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge horizontal B2:D2" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "read": { + "passed": true, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge vertical B3:B5" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "read": { + "passed": true, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with non-top-left value" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "read": { + "passed": true, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with top-left fill" + }, + "write": { + "passed": true, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "merge_horizontal": { + "read": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_horizontal", + "sheet": "merged_cells", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "error": "pylightxl does not support merge_cells: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_horizontal", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support merge_cells: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "read": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_vertical", + "sheet": "merged_cells", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "error": "pylightxl does not support merge_cells: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_vertical", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support merge_cells: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "read": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_value_off_top_left", + "sheet": "merged_cells", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "error": "pylightxl does not support merge_cells: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_value_off_top_left", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support merge_cells: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "read": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_top_left_fill", + "sheet": "merged_cells", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "error": "pylightxl does not support merge_cells: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_top_left_fill", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support merge_cells: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "merged_cells", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "merge_horizontal": { + "read": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_horizontal", + "sheet": "merged_cells", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "error": "pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_horizontal", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "read": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_vertical", + "sheet": "merged_cells", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "error": "pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_vertical", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "read": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_value_off_top_left", + "sheet": "merged_cells", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "error": "pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_value_off_top_left", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "read": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_top_left_fill", + "sheet": "merged_cells", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "error": "pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_top_left_fill", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support merge_cells: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "merge_horizontal": { + "write": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": "B2:D2", + "top_left_value": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_horizontal", + "sheet": "merged_cells", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': 'B2:D2', 'top_left_value': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "write": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": "B3:B5", + "top_left_value": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_vertical", + "sheet": "merged_cells", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': 'B3:B5', 'top_left_value': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "write": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": "B6:D6", + "top_left_value": null, + "non_top_left_nonempty": 0 + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_value_off_top_left", + "sheet": "merged_cells", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': 'B6:D6', 'top_left_value': None, 'non_top_left_nonempty': 0}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "write": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": "B7:D7", + "top_left_value": null, + "top_left_bg_color": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_top_left_fill", + "sheet": "merged_cells", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': 'B7:D7', 'top_left_value': None, 'top_left_bg_color': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "merge_horizontal": { + "read": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_horizontal", + "sheet": "merged_cells", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_horizontal", + "sheet": "merged_cells", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "read": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_vertical", + "sheet": "merged_cells", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_vertical", + "sheet": "merged_cells", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "read": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_value_off_top_left", + "sheet": "merged_cells", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_value_off_top_left", + "sheet": "merged_cells", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "read": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_top_left_fill", + "sheet": "merged_cells", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_top_left_fill", + "sheet": "merged_cells", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "merge_horizontal": { + "write": { + "passed": true, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "write": { + "passed": true, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "write": { + "passed": true, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "write": { + "passed": true, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "merge_horizontal": { + "read": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_horizontal", + "sheet": "merged_cells", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "read": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_vertical", + "sheet": "merged_cells", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "read": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_value_off_top_left", + "sheet": "merged_cells", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "read": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_top_left_fill", + "sheet": "merged_cells", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "merge_horizontal": { + "read": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_horizontal", + "sheet": "merged_cells", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "read": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_vertical", + "sheet": "merged_cells", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "read": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_value_off_top_left", + "sheet": "merged_cells", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "read": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_top_left_fill", + "sheet": "merged_cells", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "merged_cells", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "merge_horizontal": { + "read": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_horizontal", + "sheet": "merged_cells", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B2:D2", + "top_left_value": "Merged" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_horizontal", + "sheet": "merged_cells", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B2:D2', 'top_left_value': 'Merged'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge horizontal B2:D2" + } + }, + "merge_vertical": { + "read": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_vertical", + "sheet": "merged_cells", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B3:B5", + "top_left_value": "Vertical" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_vertical", + "sheet": "merged_cells", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B3:B5', 'top_left_value': 'Vertical'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "basic", + "label": "Merge vertical B3:B5" + } + }, + "merge_value_off_top_left": { + "read": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_value_off_top_left", + "sheet": "merged_cells", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B6:D6", + "top_left_value": "OffTop", + "non_top_left_nonempty": 0 + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_value_off_top_left", + "sheet": "merged_cells", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B6:D6', 'top_left_value': 'OffTop', 'non_top_left_nonempty': 0}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "merge_drift", + "suggested_next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "explanation": { + "code": "merge_drift", + "summary": "merged-cell metadata changed", + "probable_cause": "merged range XML or non-anchor cell handling differs", + "next_step": "inspect mergeCells in the worksheet XML and subordinate cell behavior", + "tag": "merge" + } + } + ], + "importance": "edge", + "label": "Merge with non-top-left value" + } + }, + "merge_top_left_fill": { + "read": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "read", + "test_case_id": "merge_top_left_fill", + "sheet": "merged_cells", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + }, + "write": { + "passed": false, + "expected": { + "merged_range": "B7:D7", + "top_left_value": "Fill", + "top_left_bg_color": "#FF0000" + }, + "actual": { + "merged_range": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "merged_cells", + "operation": "write", + "test_case_id": "merge_top_left_fill", + "sheet": "merged_cells", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'merged_range': 'B7:D7', 'top_left_value': 'Fill', 'top_left_bg_color': '#FF0000'}, actual={'merged_range': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Merge with top-left fill" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "cf_cell_gt": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "format": { + "bg_color": "#FF00FF" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "format": { + "bg_color": "#FF00FF" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: text contains" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: data bar" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: 3-color scale" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: stop-if-true priority" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "cf_cell_gt": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "format": { + "bg_color": "#FF00FF" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "cf_cell_gt": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_cell_gt", + "sheet": "conditional_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_formula_cross_sheet", + "sheet": "conditional_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_text_contains", + "sheet": "conditional_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH(\"foo\",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_data_bar", + "sheet": "conditional_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_color_scale", + "sheet": "conditional_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_stop_if_true", + "sheet": "conditional_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "cf_cell_gt": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "format": { + "bg_color": "#FF00FF" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "format": { + "bg_color": "#FF00FF" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: text contains" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: data bar" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: 3-color scale" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: stop-if-true priority" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "wolfxl", + "scores": { + "read": 0, + "write": 3 + }, + "test_cases": { + "cf_cell_gt": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "format": {} + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_cell_gt", + "sheet": "conditional_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'format': {}}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "format": {} + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_formula_cross_sheet", + "sheet": "conditional_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'format': {}}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "format": { + "bg_color": "#FF00FF" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "format": {} + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_text_contains", + "sheet": "conditional_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH(\"foo\",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH(\"foo\",B2))', 'format': {}}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: data bar" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "read": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: 3-color scale" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "stop_if_true": true, + "format": {} + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_stop_if_true", + "sheet": "conditional_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'stop_if_true': True, 'format': {}}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + }, + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "cf_cell_gt": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_cell_gt", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "error": "pylightxl does not support add_conditional_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_cell_gt", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_formula_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "error": "pylightxl does not support add_conditional_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_formula_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_text_contains", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "error": "pylightxl does not support add_conditional_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_text_contains", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_data_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "edge", + "label": "CF: data bar" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "error": "pylightxl does not support add_conditional_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_data_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_color_scale", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "error": "pylightxl does not support add_conditional_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_color_scale", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_stop_if_true", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "error": "pylightxl does not support add_conditional_format: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_stop_if_true", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_conditional_format: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "conditional_formatting", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "cf_cell_gt": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_cell_gt", + "sheet": "conditional_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "error": "pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_cell_gt", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_formula_cross_sheet", + "sheet": "conditional_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "error": "pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_formula_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_text_contains", + "sheet": "conditional_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH(\"foo\",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "error": "pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_text_contains", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_data_bar", + "sheet": "conditional_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "edge", + "label": "CF: data bar" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "error": "pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_data_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_color_scale", + "sheet": "conditional_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "error": "pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_color_scale", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_stop_if_true", + "sheet": "conditional_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "error": "pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_stop_if_true", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_conditional_format: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "cf_cell_gt": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "error": "xlwt does not support add_conditional_format: xlwt cannot author conditional formatting" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_cell_gt", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting", + "probable_cause": "xlwt cannot author conditional formatting", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author conditional formatting", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "error": "xlwt does not support add_conditional_format: xlwt cannot author conditional formatting" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_formula_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting", + "probable_cause": "xlwt cannot author conditional formatting", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author conditional formatting", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "error": "xlwt does not support add_conditional_format: xlwt cannot author conditional formatting" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_text_contains", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting", + "probable_cause": "xlwt cannot author conditional formatting", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author conditional formatting", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "error": "xlwt does not support add_conditional_format: xlwt cannot author conditional formatting" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_data_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting", + "probable_cause": "xlwt cannot author conditional formatting", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author conditional formatting", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "error": "xlwt does not support add_conditional_format: xlwt cannot author conditional formatting" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_color_scale", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting", + "probable_cause": "xlwt cannot author conditional formatting", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author conditional formatting", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "error": "xlwt does not support add_conditional_format: xlwt cannot author conditional formatting" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_stop_if_true", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_conditional_format: xlwt cannot author conditional formatting", + "probable_cause": "xlwt cannot author conditional formatting", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author conditional formatting", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "cf_cell_gt": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_cell_gt", + "sheet": "conditional_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_cell_gt", + "sheet": "conditional_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_formula_cross_sheet", + "sheet": "conditional_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_formula_cross_sheet", + "sheet": "conditional_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_text_contains", + "sheet": "conditional_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH(\"foo\",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_text_contains", + "sheet": "conditional_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH(\"foo\",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_data_bar", + "sheet": "conditional_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "edge", + "label": "CF: data bar" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_data_bar", + "sheet": "conditional_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_color_scale", + "sheet": "conditional_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_color_scale", + "sheet": "conditional_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_stop_if_true", + "sheet": "conditional_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_stop_if_true", + "sheet": "conditional_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "cf_cell_gt": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "format": { + "bg_color": "#FF00FF" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "format": { + "bg_color": "#FFFF00" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "write": { + "passed": true, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "cf_cell_gt": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_cell_gt", + "sheet": "conditional_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_formula_cross_sheet", + "sheet": "conditional_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_text_contains", + "sheet": "conditional_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH(\"foo\",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_data_bar", + "sheet": "conditional_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_color_scale", + "sheet": "conditional_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_stop_if_true", + "sheet": "conditional_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "cf_cell_gt": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_cell_gt", + "sheet": "conditional_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_formula_cross_sheet", + "sheet": "conditional_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_text_contains", + "sheet": "conditional_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH(\"foo\",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_data_bar", + "sheet": "conditional_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_color_scale", + "sheet": "conditional_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_stop_if_true", + "sheet": "conditional_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "conditional_formatting", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "cf_cell_gt": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_cell_gt", + "sheet": "conditional_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "cellIs", + "operator": "greaterThan", + "formula": "5", + "priority": 1, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_cell_gt", + "sheet": "conditional_formatting", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'cellIs', 'operator': 'greaterThan', 'formula': '5', 'priority': 1, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "CF: cell > 5 (yellow fill)" + } + }, + "cf_formula_cross_sheet": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_formula_cross_sheet", + "sheet": "conditional_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=Ref!$A$1>5", + "priority": 2, + "format": { + "bg_color": "#FF00FF" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_formula_cross_sheet", + "sheet": "conditional_formatting", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=Ref!$A$1>5', 'priority': 2, 'format': {'bg_color': '#FF00FF'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: formula rule with cross-sheet ref" + } + }, + "cf_text_contains": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_text_contains", + "sheet": "conditional_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH(\"foo\",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "expression", + "formula": "=ISNUMBER(SEARCH(\"foo\",B2))", + "priority": 3, + "format": { + "bg_color": "#FFFF00" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_text_contains", + "sheet": "conditional_formatting", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'expression', 'formula': '=ISNUMBER(SEARCH(\"foo\",B2))', 'priority': 3, 'format': {'bg_color': '#FFFF00'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: text contains" + } + }, + "cf_data_bar": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_data_bar", + "sheet": "conditional_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "edge", + "label": "CF: data bar" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "dataBar", + "priority": 4 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_data_bar", + "sheet": "conditional_formatting", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'dataBar', 'priority': 4}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "edge", + "label": "CF: data bar" + } + }, + "cf_color_scale": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_color_scale", + "sheet": "conditional_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B2:B6", + "rule_type": "colorScale", + "priority": 5 + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_color_scale", + "sheet": "conditional_formatting", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B2:B6', 'rule_type': 'colorScale', 'priority': 5}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: 3-color scale" + } + }, + "cf_stop_if_true": { + "read": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "read", + "test_case_id": "cf_stop_if_true", + "sheet": "conditional_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + }, + "write": { + "passed": false, + "expected": { + "cf_rule": { + "range": "B7:B9", + "rule_type": "cellIs", + "operator": "lessThan", + "formula": "3", + "priority": 1, + "stop_if_true": true, + "format": { + "bg_color": "#FF0000" + } + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "conditional_formatting", + "operation": "write", + "test_case_id": "cf_stop_if_true", + "sheet": "conditional_formatting", + "cell": "B7" + }, + "adapter_message": "Expected values did not match actual values: expected={'cf_rule': {'range': 'B7:B9', 'rule_type': 'cellIs', 'operator': 'lessThan', 'formula': '3', 'priority': 1, 'stop_if_true': True, 'format': {'bg_color': '#FF0000'}}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "CF: stop-if-true priority" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "dv_list_csv": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: list from CSV" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: list from range" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: cross-sheet named range" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: custom formula" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: whole number with error" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "dv_list_csv": { + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "dv_list_csv": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_csv", + "sheet": "data_validation", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '\"Red,Green,Blue\"', 'allow_blank': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_range", + "sheet": "data_validation", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_cross_sheet", + "sheet": "data_validation", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_custom_formula", + "sheet": "data_validation", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_whole_between", + "sheet": "data_validation", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "dv_list_csv": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: list from CSV" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: list from range" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: cross-sheet named range" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: custom formula" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: whole number with error" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "dv_list_csv": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: list from CSV" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: list from range" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: cross-sheet named range" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: custom formula" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "read": { + "passed": true, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: whole number with error" + }, + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "dv_list_csv": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_csv", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "error": "pylightxl does not support add_data_validation: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_csv", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_data_validation: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_range", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "error": "pylightxl does not support add_data_validation: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_range", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_data_validation: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "error": "pylightxl does not support add_data_validation: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_data_validation: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_custom_formula", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "error": "pylightxl does not support add_data_validation: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_custom_formula", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_data_validation: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_whole_between", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "error": "pylightxl does not support add_data_validation: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_whole_between", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_data_validation: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "data_validation", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "dv_list_csv": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_csv", + "sheet": "data_validation", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '\"Red,Green,Blue\"', 'allow_blank': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "error": "pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_csv", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_range", + "sheet": "data_validation", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "error": "pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_range", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_cross_sheet", + "sheet": "data_validation", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "error": "pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_custom_formula", + "sheet": "data_validation", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "error": "pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_custom_formula", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_whole_between", + "sheet": "data_validation", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "error": "pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_whole_between", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_data_validation: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "dv_list_csv": { + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "error": "xlwt does not support add_data_validation: xlwt cannot author data validations" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_csv", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_data_validation: xlwt cannot author data validations", + "probable_cause": "xlwt cannot author data validations", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author data validations", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "error": "xlwt does not support add_data_validation: xlwt cannot author data validations" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_range", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_data_validation: xlwt cannot author data validations", + "probable_cause": "xlwt cannot author data validations", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author data validations", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "error": "xlwt does not support add_data_validation: xlwt cannot author data validations" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_data_validation: xlwt cannot author data validations", + "probable_cause": "xlwt cannot author data validations", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author data validations", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "error": "xlwt does not support add_data_validation: xlwt cannot author data validations" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_custom_formula", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_data_validation: xlwt cannot author data validations", + "probable_cause": "xlwt cannot author data validations", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author data validations", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "error": "xlwt does not support add_data_validation: xlwt cannot author data validations" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_whole_between", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_data_validation: xlwt cannot author data validations", + "probable_cause": "xlwt cannot author data validations", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author data validations", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "dv_list_csv": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_csv", + "sheet": "data_validation", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '\"Red,Green,Blue\"', 'allow_blank': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_csv", + "sheet": "data_validation", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '\"Red,Green,Blue\"', 'allow_blank': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_range", + "sheet": "data_validation", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_range", + "sheet": "data_validation", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_cross_sheet", + "sheet": "data_validation", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_cross_sheet", + "sheet": "data_validation", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_custom_formula", + "sheet": "data_validation", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_custom_formula", + "sheet": "data_validation", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_whole_between", + "sheet": "data_validation", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_whole_between", + "sheet": "data_validation", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "dv_list_csv": { + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "write": { + "passed": true, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "dv_list_csv": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_csv", + "sheet": "data_validation", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '\"Red,Green,Blue\"', 'allow_blank': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_range", + "sheet": "data_validation", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_cross_sheet", + "sheet": "data_validation", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_custom_formula", + "sheet": "data_validation", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_whole_between", + "sheet": "data_validation", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "dv_list_csv": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_csv", + "sheet": "data_validation", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '\"Red,Green,Blue\"', 'allow_blank': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_range", + "sheet": "data_validation", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_cross_sheet", + "sheet": "data_validation", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_custom_formula", + "sheet": "data_validation", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_whole_between", + "sheet": "data_validation", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "data_validation", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "dv_list_csv": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_csv", + "sheet": "data_validation", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '\"Red,Green,Blue\"', 'allow_blank': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B2", + "validation_type": "list", + "formula1": "\"Red,Green,Blue\"", + "allow_blank": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_csv", + "sheet": "data_validation", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B2', 'validation_type': 'list', 'formula1': '\"Red,Green,Blue\"', 'allow_blank': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: list from CSV" + } + }, + "dv_list_range": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_list_range", + "sheet": "data_validation", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B3", + "validation_type": "list", + "formula1": "=$D$2:$D$4" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_list_range", + "sheet": "data_validation", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B3', 'validation_type': 'list', 'formula1': '=$D$2:$D$4'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: list from range" + } + }, + "dv_cross_sheet": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_cross_sheet", + "sheet": "data_validation", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B4", + "validation_type": "list", + "formula1": "=RegionList" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_cross_sheet", + "sheet": "data_validation", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B4', 'validation_type': 'list', 'formula1': '=RegionList'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: cross-sheet named range" + } + }, + "dv_custom_formula": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_custom_formula", + "sheet": "data_validation", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B5", + "validation_type": "custom", + "formula1": "=B5>C5" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_custom_formula", + "sheet": "data_validation", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B5', 'validation_type': 'custom', 'formula1': '=B5>C5'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "edge", + "label": "DV: custom formula" + } + }, + "dv_whole_between": { + "read": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "read", + "test_case_id": "dv_whole_between", + "sheet": "data_validation", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + }, + "write": { + "passed": false, + "expected": { + "validation": { + "range": "B6", + "validation_type": "whole", + "operator": "between", + "formula1": "1", + "formula2": "10", + "allow_blank": false, + "error_title": "Invalid", + "error": "Enter 1-10" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "data_validation", + "operation": "write", + "test_case_id": "dv_whole_between", + "sheet": "data_validation", + "cell": "B6" + }, + "adapter_message": "Expected values did not match actual values: expected={'validation': {'range': 'B6', 'validation_type': 'whole', 'operator': 'between', 'formula1': '1', 'formula2': '10', 'allow_blank': False, 'error_title': 'Invalid', 'error': 'Enter 1-10'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "data_validation_drift", + "suggested_next_step": "inspect dataValidations in the worksheet XML", + "explanation": { + "code": "data_validation_drift", + "summary": "data validation metadata changed", + "probable_cause": "validation type, formula, or target range was dropped or rewritten", + "next_step": "inspect dataValidations in the worksheet XML", + "tag": "validation" + } + } + ], + "importance": "basic", + "label": "DV: whole number with error" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "link_external": { + "read": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: external URL" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "read": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: internal sheet" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "read": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: mailto" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "read": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "link_external": { + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "link_external": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_external", + "sheet": "hyperlinks", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_internal", + "sheet": "hyperlinks", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_mailto", + "sheet": "hyperlinks", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_long", + "sheet": "hyperlinks", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "aspose-cells-foss", + "scores": { + "read": 0, + "write": 3 + }, + "test_cases": { + "link_external": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": null, + "tooltip": "Go to docs", + "internal": false + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_external", + "sheet": "hyperlinks", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': None, 'tooltip': 'Go to docs', 'internal': False}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": null, + "tooltip": "Jump to target", + "internal": true + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_internal", + "sheet": "hyperlinks", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': None, 'tooltip': 'Jump to target', 'internal': True}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": null, + "tooltip": "Send email", + "internal": false + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_mailto", + "sheet": "hyperlinks", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': None, 'tooltip': 'Send email', 'internal': False}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": null, + "tooltip": "Encoded URL", + "internal": false + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_long", + "sheet": "hyperlinks", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': None, 'tooltip': 'Encoded URL', 'internal': False}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "link_external": { + "read": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: external URL" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "read": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: internal sheet" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "read": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: mailto" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "read": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + }, + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "link_external": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_external", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "error": "pylightxl does not support add_hyperlink: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_external", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_hyperlink: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_internal", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "error": "pylightxl does not support add_hyperlink: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_internal", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_hyperlink: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_mailto", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "error": "pylightxl does not support add_hyperlink: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_mailto", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_hyperlink: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_long", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "error": "pylightxl does not support add_hyperlink: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_long", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_hyperlink: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "hyperlinks", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "link_external": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_external", + "sheet": "hyperlinks", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "error": "pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_external", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_internal", + "sheet": "hyperlinks", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "error": "pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_internal", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_mailto", + "sheet": "hyperlinks", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "error": "pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_mailto", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_long", + "sheet": "hyperlinks", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "error": "pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_long", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_hyperlink: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "link_external": { + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "error": "xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_external", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter", + "probable_cause": "xlwt hyperlink metadata is not supported in this adapter", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt hyperlink metadata is not supported in this adapter", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "error": "xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_internal", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter", + "probable_cause": "xlwt hyperlink metadata is not supported in this adapter", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt hyperlink metadata is not supported in this adapter", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "error": "xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_mailto", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter", + "probable_cause": "xlwt hyperlink metadata is not supported in this adapter", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt hyperlink metadata is not supported in this adapter", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "error": "xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_long", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_hyperlink: xlwt hyperlink metadata is not supported in this adapter", + "probable_cause": "xlwt hyperlink metadata is not supported in this adapter", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt hyperlink metadata is not supported in this adapter", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "link_external": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_external", + "sheet": "hyperlinks", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_external", + "sheet": "hyperlinks", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_internal", + "sheet": "hyperlinks", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_internal", + "sheet": "hyperlinks", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_mailto", + "sheet": "hyperlinks", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_mailto", + "sheet": "hyperlinks", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_long", + "sheet": "hyperlinks", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_long", + "sheet": "hyperlinks", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "link_external": { + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "write": { + "passed": true, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "link_external": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_external", + "sheet": "hyperlinks", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_internal", + "sheet": "hyperlinks", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_mailto", + "sheet": "hyperlinks", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_long", + "sheet": "hyperlinks", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "link_external": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_external", + "sheet": "hyperlinks", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_internal", + "sheet": "hyperlinks", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_mailto", + "sheet": "hyperlinks", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_long", + "sheet": "hyperlinks", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "hyperlinks", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "link_external": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_external", + "sheet": "hyperlinks", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B2", + "target": "https://example.com/docs", + "display": "Example Docs", + "tooltip": "Go to docs", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_external", + "sheet": "hyperlinks", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B2', 'target': 'https://example.com/docs', 'display': 'Example Docs', 'tooltip': 'Go to docs', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: external URL" + } + }, + "link_internal": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_internal", + "sheet": "hyperlinks", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B3", + "target": "Targets!A1", + "display": "Go Target", + "tooltip": "Jump to target", + "internal": true + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_internal", + "sheet": "hyperlinks", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B3', 'target': 'Targets!A1', 'display': 'Go Target', 'tooltip': 'Jump to target', 'internal': True}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: internal sheet" + } + }, + "link_mailto": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_mailto", + "sheet": "hyperlinks", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B4", + "target": "mailto:test@example.com", + "display": "Email", + "tooltip": "Send email", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_mailto", + "sheet": "hyperlinks", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B4', 'target': 'mailto:test@example.com', 'display': 'Email', 'tooltip': 'Send email', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "basic", + "label": "Hyperlink: mailto" + } + }, + "link_long": { + "read": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "read", + "test_case_id": "link_long", + "sheet": "hyperlinks", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + }, + "write": { + "passed": false, + "expected": { + "hyperlink": { + "cell": "B5", + "target": "https://example.com/search?q=excel%20bench&sort=desc#section-2", + "display": "Search", + "tooltip": "Encoded URL", + "internal": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "hyperlinks", + "operation": "write", + "test_case_id": "link_long", + "sheet": "hyperlinks", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'hyperlink': {'cell': 'B5', 'target': 'https://example.com/search?q=excel%20bench&sort=desc#section-2', 'display': 'Search', 'tooltip': 'Encoded URL', 'internal': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "hyperlink_drift", + "suggested_next_step": "inspect worksheet hyperlinks and worksheet rels", + "explanation": { + "code": "hyperlink_drift", + "summary": "hyperlink target or display metadata changed", + "probable_cause": "hyperlink rel target, tooltip, or internal location was not preserved", + "next_step": "inspect worksheet hyperlinks and worksheet rels", + "tag": "hyperlink" + } + } + ], + "importance": "edge", + "label": "Hyperlink: long encoded URL" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "image_one_cell": { + "read": { + "passed": true, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Image: one-cell anchor" + }, + "write": { + "passed": true, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "read": { + "passed": true, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + }, + "write": { + "passed": true, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "image_one_cell": { + "write": { + "passed": true, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "write": { + "passed": true, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "image_one_cell": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_one_cell", + "sheet": "images", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_two_cell_offset", + "sheet": "images", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "aspose-cells-foss", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "image_one_cell": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "error": "aspose-cells-foss does not support read_images: aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind." + }, + "notes": "Exception: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_one_cell", + "sheet": "images", + "cell": "B2" + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support read_images: aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind.", + "probable_cause": "aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + }, + "write": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "error": "aspose-cells-foss does not support add_image: aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_one_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support add_image: aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors.", + "probable_cause": "aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "error": "aspose-cells-foss does not support read_images: aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind." + }, + "notes": "Exception: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_two_cell_offset", + "sheet": "images", + "cell": "B3" + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support read_images: aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind.", + "probable_cause": "aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + }, + "write": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "error": "aspose-cells-foss does not support add_image: aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_two_cell_offset", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support add_image: aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors.", + "probable_cause": "aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss writes only two-cell picture anchors, while the benchmark requires one-cell anchors.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "image_one_cell": { + "read": { + "passed": true, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Image: one-cell anchor" + }, + "write": { + "passed": true, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "read": { + "passed": true, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + }, + "write": { + "passed": true, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "image_one_cell": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_one_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + }, + "write": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "error": "pylightxl does not support add_image: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_one_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_image: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_two_cell_offset", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + }, + "write": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "error": "pylightxl does not support add_image: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_two_cell_offset", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_image: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "images", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "image_one_cell": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_one_cell", + "sheet": "images", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + }, + "write": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "error": "pyexcel does not support add_image: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_one_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_image: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_two_cell_offset", + "sheet": "images", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + }, + "write": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "error": "pyexcel does not support add_image: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_two_cell_offset", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_image: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "image_one_cell": { + "write": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": { + "error": "xlwt does not support add_image: xlwt cannot embed images in this adapter" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_one_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_image: xlwt cannot embed images in this adapter", + "probable_cause": "xlwt cannot embed images in this adapter", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot embed images in this adapter", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "write": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": { + "error": "xlwt does not support add_image: xlwt cannot embed images in this adapter" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_two_cell_offset", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_image: xlwt cannot embed images in this adapter", + "probable_cause": "xlwt cannot embed images in this adapter", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot embed images in this adapter", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "image_one_cell": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_one_cell", + "sheet": "images", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + }, + "write": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_one_cell", + "sheet": "images", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_two_cell_offset", + "sheet": "images", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + }, + "write": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_two_cell_offset", + "sheet": "images", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "image_one_cell": { + "write": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_one_cell", + "sheet": "images", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "write": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_two_cell_offset", + "sheet": "images", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "image_one_cell": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_one_cell", + "sheet": "images", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_two_cell_offset", + "sheet": "images", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "image_one_cell": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_one_cell", + "sheet": "images", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_two_cell_offset", + "sheet": "images", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "images", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "image_one_cell": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_one_cell", + "sheet": "images", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + }, + "write": { + "passed": false, + "expected": { + "image": { + "cell": "B2", + "path": "fixtures/images/sample.png", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_one_cell", + "sheet": "images", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'B2', 'path': 'fixtures/images/sample.png', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Image: one-cell anchor" + } + }, + "image_two_cell_offset": { + "read": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "read", + "test_case_id": "image_two_cell_offset", + "sheet": "images", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + }, + "write": { + "passed": false, + "expected": { + "image": { + "cell": "D6", + "path": "fixtures/images/sample.jpg", + "anchor": "oneCell" + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "images", + "operation": "write", + "test_case_id": "image_two_cell_offset", + "sheet": "images", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'image': {'cell': 'D6', 'path': 'fixtures/images/sample.jpg', 'anchor': 'oneCell'}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Image: two-cell anchor with offset" + } + } + }, + "notes": null + }, + { + "feature": "pivot_tables", + "library": "openpyxl", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "python-calamine", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "aspose-cells-foss", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "wolfxl", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "pylightxl", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "pivot_tables", + "library": "pyexcel", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "xlwt", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "pandas", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "openpyxl-readonly", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "polars", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "pivot_tables", + "library": "tablib", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Unsupported on macOS without a Windows-generated pivot fixture (fixtures/excel/tier2/15_pivot_tables.xlsx)." + }, + { + "feature": "comments", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "comment_legacy": { + "read": { + "passed": true, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Comment: legacy note" + }, + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "read": { + "passed": true, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: threaded" + }, + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "read": { + "passed": true, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: second author" + }, + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "comment_legacy": { + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "comment_legacy": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 0 + }, + "test_cases": { + "comment_legacy": { + "read": { + "passed": true, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Comment: legacy note" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B2", + "text": "None:Legacy note", + "threaded": false + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={'comment': {'cell': 'B2', 'text': 'None:Legacy note', 'threaded': False}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "read": { + "passed": true, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: threaded" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B3", + "text": "None:Threaded fallback", + "threaded": false + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={'comment': {'cell': 'B3', 'text': 'None:Threaded fallback', 'threaded': False}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "read": { + "passed": true, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: second author" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B4", + "text": "None:Another note", + "threaded": false + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={'comment': {'cell': 'B4', 'text': 'None:Another note', 'threaded': False}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "comment_legacy": { + "read": { + "passed": true, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Comment: legacy note" + }, + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "read": { + "passed": true, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: threaded" + }, + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "read": { + "passed": true, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: second author" + }, + "write": { + "passed": true, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "comment_legacy": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "error": "pylightxl does not support add_comment: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_legacy", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_comment: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "error": "pylightxl does not support add_comment: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_threaded", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_comment: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "error": "pylightxl does not support add_comment: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_author", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support add_comment: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "comments", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "comment_legacy": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "error": "pyexcel does not support add_comment: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_legacy", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_comment: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "error": "pyexcel does not support add_comment: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_threaded", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_comment: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "error": "pyexcel does not support add_comment: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_author", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support add_comment: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "comment_legacy": { + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": { + "error": "xlwt does not support add_comment: xlwt cannot author comments" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_legacy", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_comment: xlwt cannot author comments", + "probable_cause": "xlwt cannot author comments", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author comments", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": { + "error": "xlwt does not support add_comment: xlwt cannot author comments" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_threaded", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_comment: xlwt cannot author comments", + "probable_cause": "xlwt cannot author comments", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author comments", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": { + "error": "xlwt does not support add_comment: xlwt cannot author comments" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_author", + "sheet": null, + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: xlwt does not support add_comment: xlwt cannot author comments", + "probable_cause": "xlwt cannot author comments", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "xlwt cannot author comments", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "comment_legacy": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "comment_legacy": { + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "comment_legacy": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "comment_legacy": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "comments", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "comment_legacy": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B2", + "text": "Legacy note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_legacy", + "sheet": "comments", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B2', 'text': 'Legacy note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "basic", + "label": "Comment: legacy note" + } + }, + "comment_threaded": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B3", + "text": "Threaded fallback", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_threaded", + "sheet": "comments", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B3', 'text': 'Threaded fallback', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: threaded" + } + }, + "comment_author": { + "read": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "read", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + }, + "write": { + "passed": false, + "expected": { + "comment": { + "cell": "B4", + "text": "Another note", + "threaded": false + } + }, + "actual": {}, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "comments", + "operation": "write", + "test_case_id": "comment_author", + "sheet": "comments", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'comment': {'cell': 'B4', 'text': 'Another note', 'threaded': False}}, actual={}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "comment_drift", + "suggested_next_step": "inspect comments XML plus VML drawing relationships", + "explanation": { + "code": "comment_drift", + "summary": "comment metadata changed", + "probable_cause": "legacy comment text, author, or VML relationship was not preserved", + "next_step": "inspect comments XML plus VML drawing relationships", + "tag": "comment" + } + } + ], + "importance": "edge", + "label": "Comment: second author" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "freeze_b2": { + "read": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Freeze panes at B2" + }, + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "read": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Freeze panes at D5" + }, + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "read": { + "passed": true, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Split panes row=2 col=1" + }, + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "freeze_b2": { + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "freeze_b2": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": null, + "x_split": null, + "y_split": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "freeze_b2": { + "read": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Freeze panes at B2" + }, + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "read": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Freeze panes at D5" + }, + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "read": { + "passed": true, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Split panes row=2 col=1" + }, + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "freeze_b2": { + "read": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Freeze panes at B2" + }, + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "read": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Freeze panes at D5" + }, + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "read": { + "passed": true, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Split panes row=2 col=1" + }, + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "freeze_b2": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "error": "pylightxl does not support set_freeze_panes: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support set_freeze_panes: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "error": "pylightxl does not support set_freeze_panes: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support set_freeze_panes: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "error": "pylightxl does not support set_freeze_panes: pylightxl does not implement this feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pylightxl does not support set_freeze_panes: pylightxl does not implement this feature", + "probable_cause": "pylightxl does not implement this feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pylightxl does not implement this feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "freeze_panes", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "freeze_b2": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "error": "pyexcel does not support set_freeze_panes: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support set_freeze_panes: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "error": "pyexcel does not support set_freeze_panes: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support set_freeze_panes: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": null, + "x_split": null, + "y_split": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "error": "pyexcel does not support set_freeze_panes: pyexcel does not expose this worksheet feature" + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: pyexcel does not support set_freeze_panes: pyexcel does not expose this worksheet feature", + "probable_cause": "pyexcel does not expose this worksheet feature", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "pyexcel does not expose this worksheet feature", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "freeze_b2": { + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "error": "'Sheet' object has no attribute 'frozen_row_count'" + }, + "notes": "Exception: AttributeError", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": "B2" + }, + "adapter_message": "AttributeError: 'Sheet' object has no attribute 'frozen_row_count'", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "error": "'Sheet' object has no attribute 'frozen_row_count'" + }, + "notes": "Exception: AttributeError", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": "B3" + }, + "adapter_message": "AttributeError: 'Sheet' object has no attribute 'frozen_row_count'", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "error": "'Sheet' object has no attribute 'frozen_row_count'" + }, + "notes": "Exception: AttributeError", + "diagnostics": [ + { + "category": "internal", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": "B4" + }, + "adapter_message": "AttributeError: 'Sheet' object has no attribute 'frozen_row_count'", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "freeze_b2": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": null, + "x_split": null, + "y_split": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": null, + "x_split": null, + "y_split": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 3 + }, + "test_cases": { + "freeze_b2": { + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "write": { + "passed": true, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "freeze_b2": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": null, + "x_split": null, + "y_split": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "freeze_b2": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": null, + "x_split": null, + "y_split": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "freeze_panes", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "freeze_b2": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "B2" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_b2", + "sheet": "FreezeB2", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'B2'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "basic", + "label": "Freeze panes at B2" + } + }, + "freeze_d5": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "freeze", + "top_left_cell": "D5" + } + }, + "actual": { + "freeze": { + "mode": null, + "top_left_cell": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "freeze_d5", + "sheet": "FreezeD5", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'freeze', 'top_left_cell': 'D5'}}, actual={'freeze': {'mode': None, 'top_left_cell': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Freeze panes at D5" + } + }, + "split_2x1": { + "read": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": null, + "x_split": null, + "y_split": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "read", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + }, + "write": { + "passed": false, + "expected": { + "freeze": { + "mode": "split", + "x_split": 1, + "y_split": 2 + } + }, + "actual": { + "freeze": { + "mode": null, + "x_split": null, + "y_split": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "freeze_panes", + "operation": "write", + "test_case_id": "split_2x1", + "sheet": "SplitPanes", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'freeze': {'mode': 'split', 'x_split': 1, 'y_split': 2}}, actual={'freeze': {'mode': None, 'x_split': None, 'y_split': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "freeze_pane_drift", + "suggested_next_step": "inspect sheetViews/pane in the worksheet XML", + "explanation": { + "code": "freeze_pane_drift", + "summary": "freeze pane settings changed", + "probable_cause": "pane split/top-left metadata was dropped or normalized incorrectly", + "next_step": "inspect sheetViews/pane in the worksheet XML", + "tag": "freeze_pane" + } + } + ], + "importance": "edge", + "label": "Split panes row=2 col=1" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "nr_simple_cell": { + "read": { + "passed": true, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: single cell" + }, + "write": { + "passed": true, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "read": { + "passed": true, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: cell range" + }, + "write": { + "passed": true, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "read": { + "passed": true, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: used in formula" + }, + "write": { + "passed": true, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "read": { + "passed": true, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: sheet-scoped" + }, + "write": { + "passed": true, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "read": { + "passed": true, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: cross-sheet reference" + }, + "write": { + "passed": true, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "read": { + "passed": true, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: underscore name" + }, + "write": { + "passed": true, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "nr_simple_cell": { + "write": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "xlsxwriter does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_simple_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "write": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "xlsxwriter does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cell_range", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "write": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "xlsxwriter does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_formula_ref", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "write": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "xlsxwriter does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_sheet_scope", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "write": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "xlsxwriter does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "write": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "xlsxwriter does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_special_chars", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "nr_simple_cell": { + "read": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "python-calamine does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_simple_cell", + "sheet": "named_ranges", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "read": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "python-calamine does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cell_range", + "sheet": "named_ranges", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "read": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "python-calamine does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_formula_ref", + "sheet": "named_ranges", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "read": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "python-calamine does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_sheet_scope", + "sheet": "named_ranges", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "read": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "python-calamine does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cross_sheet", + "sheet": "named_ranges", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "read": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "python-calamine does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_special_chars", + "sheet": "named_ranges", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "aspose-cells-foss", + "scores": { + "read": 2, + "write": 3 + }, + "test_cases": { + "nr_simple_cell": { + "read": { + "passed": true, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: single cell" + }, + "write": { + "passed": true, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "read": { + "passed": true, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: cell range" + }, + "write": { + "passed": true, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "read": { + "passed": true, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: used in formula" + }, + "write": { + "passed": true, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "read": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": null + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_sheet_scope", + "sheet": "named_ranges", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'name': 'LocalName', 'scope': 'sheet', 'refers_to': 'named_ranges!$B$5', 'value': 'local'}, actual={'name': 'LocalName', 'scope': 'sheet', 'refers_to': 'named_ranges!$B$5', 'value': None}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "named_range_scope_drift", + "suggested_next_step": "inspect workbook.xml definedNames and localSheetId values", + "explanation": { + "code": "named_range_scope_drift", + "summary": "named range metadata changed", + "probable_cause": "workbook-level vs sheet-level defined-name scope was lost or rewritten", + "next_step": "inspect workbook.xml definedNames and localSheetId values", + "tag": "named_range" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + }, + "write": { + "passed": true, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "read": { + "passed": true, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: cross-sheet reference" + }, + "write": { + "passed": true, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "read": { + "passed": true, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: underscore name" + }, + "write": { + "passed": true, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 2 + }, + "test_cases": { + "nr_simple_cell": { + "read": { + "passed": true, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: single cell" + }, + "write": { + "passed": true, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "read": { + "passed": true, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: cell range" + }, + "write": { + "passed": true, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "read": { + "passed": true, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: used in formula" + }, + "write": { + "passed": true, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "read": { + "passed": true, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: sheet-scoped" + }, + "write": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "name": "LocalName", + "scope": "not_found", + "refers_to": "" + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_sheet_scope", + "sheet": "named_ranges", + "cell": "B5" + }, + "adapter_message": "Expected values did not match actual values: expected={'name': 'LocalName', 'scope': 'sheet', 'refers_to': 'named_ranges!$B$5', 'value': 'local'}, actual={'name': 'LocalName', 'scope': 'not_found', 'refers_to': ''}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "named_range_scope_drift", + "suggested_next_step": "inspect workbook.xml definedNames and localSheetId values", + "explanation": { + "code": "named_range_scope_drift", + "summary": "named range metadata changed", + "probable_cause": "workbook-level vs sheet-level defined-name scope was lost or rewritten", + "next_step": "inspect workbook.xml definedNames and localSheetId values", + "tag": "named_range" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "read": { + "passed": true, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: cross-sheet reference" + }, + "write": { + "passed": true, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "read": { + "passed": true, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: underscore name" + }, + "write": { + "passed": true, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "nr_simple_cell": { + "read": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_simple_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "named_range_scope_drift", + "suggested_next_step": "inspect workbook.xml definedNames and localSheetId values", + "explanation": { + "code": "named_range_scope_drift", + "summary": "named range metadata changed", + "probable_cause": "workbook-level vs sheet-level defined-name scope was lost or rewritten", + "next_step": "inspect workbook.xml definedNames and localSheetId values", + "tag": "named_range" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + }, + "write": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "pylightxl does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_simple_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "read": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cell_range", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "named_range_scope_drift", + "suggested_next_step": "inspect workbook.xml definedNames and localSheetId values", + "explanation": { + "code": "named_range_scope_drift", + "summary": "named range metadata changed", + "probable_cause": "workbook-level vs sheet-level defined-name scope was lost or rewritten", + "next_step": "inspect workbook.xml definedNames and localSheetId values", + "tag": "named_range" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + }, + "write": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "pylightxl does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cell_range", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "read": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_formula_ref", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "named_range_scope_drift", + "suggested_next_step": "inspect workbook.xml definedNames and localSheetId values", + "explanation": { + "code": "named_range_scope_drift", + "summary": "named range metadata changed", + "probable_cause": "workbook-level vs sheet-level defined-name scope was lost or rewritten", + "next_step": "inspect workbook.xml definedNames and localSheetId values", + "tag": "named_range" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + }, + "write": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "pylightxl does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_formula_ref", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "read": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_sheet_scope", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "named_range_scope_drift", + "suggested_next_step": "inspect workbook.xml definedNames and localSheetId values", + "explanation": { + "code": "named_range_scope_drift", + "summary": "named range metadata changed", + "probable_cause": "workbook-level vs sheet-level defined-name scope was lost or rewritten", + "next_step": "inspect workbook.xml definedNames and localSheetId values", + "tag": "named_range" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + }, + "write": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "pylightxl does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_sheet_scope", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "read": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "named_range_scope_drift", + "suggested_next_step": "inspect workbook.xml definedNames and localSheetId values", + "explanation": { + "code": "named_range_scope_drift", + "summary": "named range metadata changed", + "probable_cause": "workbook-level vs sheet-level defined-name scope was lost or rewritten", + "next_step": "inspect workbook.xml definedNames and localSheetId values", + "tag": "named_range" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + }, + "write": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "pylightxl does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "read": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_special_chars", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "named_range_scope_drift", + "suggested_next_step": "inspect workbook.xml definedNames and localSheetId values", + "explanation": { + "code": "named_range_scope_drift", + "summary": "named range metadata changed", + "probable_cause": "workbook-level vs sheet-level defined-name scope was lost or rewritten", + "next_step": "inspect workbook.xml definedNames and localSheetId values", + "tag": "named_range" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + }, + "write": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "pylightxl does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_special_chars", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "named_ranges", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "nr_simple_cell": { + "read": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "pyexcel does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_simple_cell", + "sheet": "named_ranges", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + }, + "write": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "pyexcel does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_simple_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "read": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "pyexcel does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cell_range", + "sheet": "named_ranges", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + }, + "write": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "pyexcel does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cell_range", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "read": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "pyexcel does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_formula_ref", + "sheet": "named_ranges", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + }, + "write": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "pyexcel does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_formula_ref", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "read": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "pyexcel does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_sheet_scope", + "sheet": "named_ranges", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + }, + "write": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "pyexcel does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_sheet_scope", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "read": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "pyexcel does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cross_sheet", + "sheet": "named_ranges", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + }, + "write": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "pyexcel does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "read": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "pyexcel does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_special_chars", + "sheet": "named_ranges", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + }, + "write": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "pyexcel does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_special_chars", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "nr_simple_cell": { + "write": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "xlwt does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_simple_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "write": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "xlwt does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cell_range", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "write": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "xlwt does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_formula_ref", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "write": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "xlwt does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_sheet_scope", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "write": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "xlwt does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "write": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "xlwt does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_special_chars", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "nr_simple_cell": { + "read": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "pandas does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_simple_cell", + "sheet": "named_ranges", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pandas does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + }, + "write": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "pandas does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_simple_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "read": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "pandas does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cell_range", + "sheet": "named_ranges", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: pandas does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + }, + "write": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "pandas does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cell_range", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "read": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "pandas does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_formula_ref", + "sheet": "named_ranges", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: pandas does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + }, + "write": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "pandas does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_formula_ref", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "read": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "pandas does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_sheet_scope", + "sheet": "named_ranges", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: pandas does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + }, + "write": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "pandas does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_sheet_scope", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "read": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "pandas does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cross_sheet", + "sheet": "named_ranges", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: pandas does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + }, + "write": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "pandas does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "read": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "pandas does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_special_chars", + "sheet": "named_ranges", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: pandas does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + }, + "write": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "pandas does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_special_chars", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "nr_simple_cell": { + "write": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "xlsxwriter-constmem does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_simple_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "write": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "xlsxwriter-constmem does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cell_range", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "write": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "xlsxwriter-constmem does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_formula_ref", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "write": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "xlsxwriter-constmem does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_sheet_scope", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "write": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "xlsxwriter-constmem does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "write": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "xlsxwriter-constmem does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_special_chars", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "nr_simple_cell": { + "read": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "openpyxl-readonly does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_simple_cell", + "sheet": "named_ranges", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "read": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "openpyxl-readonly does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cell_range", + "sheet": "named_ranges", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "read": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "openpyxl-readonly does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_formula_ref", + "sheet": "named_ranges", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "read": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "openpyxl-readonly does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_sheet_scope", + "sheet": "named_ranges", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "read": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "openpyxl-readonly does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cross_sheet", + "sheet": "named_ranges", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "read": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "openpyxl-readonly does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_special_chars", + "sheet": "named_ranges", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "nr_simple_cell": { + "read": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "polars does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_simple_cell", + "sheet": "named_ranges", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: polars does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "read": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "polars does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cell_range", + "sheet": "named_ranges", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: polars does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "read": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "polars does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_formula_ref", + "sheet": "named_ranges", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: polars does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "read": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "polars does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_sheet_scope", + "sheet": "named_ranges", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: polars does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "read": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "polars does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cross_sheet", + "sheet": "named_ranges", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: polars does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "read": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "polars does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_special_chars", + "sheet": "named_ranges", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: polars does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "named_ranges", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "nr_simple_cell": { + "read": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "tablib does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_simple_cell", + "sheet": "named_ranges", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: tablib does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + }, + "write": { + "passed": false, + "expected": { + "name": "SingleCell", + "scope": "workbook", + "refers_to": "named_ranges!$B$2", + "value": 42 + }, + "actual": { + "error": "tablib does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_simple_cell", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: single cell" + } + }, + "nr_cell_range": { + "read": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "tablib does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cell_range", + "sheet": "named_ranges", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: tablib does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + }, + "write": { + "passed": false, + "expected": { + "name": "DataRange", + "scope": "workbook", + "refers_to": "named_ranges!$B$3:$D$3" + }, + "actual": { + "error": "tablib does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cell_range", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: cell range" + } + }, + "nr_formula_ref": { + "read": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "tablib does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_formula_ref", + "sheet": "named_ranges", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: tablib does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + }, + "write": { + "passed": false, + "expected": { + "name": "TaxRate", + "scope": "workbook", + "refers_to": "named_ranges!$B$4", + "value": 0.08 + }, + "actual": { + "error": "tablib does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_formula_ref", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Named range: used in formula" + } + }, + "nr_sheet_scope": { + "read": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "tablib does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_sheet_scope", + "sheet": "named_ranges", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: tablib does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + }, + "write": { + "passed": false, + "expected": { + "name": "LocalName", + "scope": "sheet", + "refers_to": "named_ranges!$B$5", + "value": "local" + }, + "actual": { + "error": "tablib does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_sheet_scope", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: sheet-scoped" + } + }, + "nr_cross_sheet": { + "read": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "tablib does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_cross_sheet", + "sheet": "named_ranges", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: tablib does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + }, + "write": { + "passed": false, + "expected": { + "name": "OtherSheet", + "scope": "workbook", + "refers_to": "Targets!$A$1" + }, + "actual": { + "error": "tablib does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_cross_sheet", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: cross-sheet reference" + } + }, + "nr_special_chars": { + "read": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "tablib does not implement named range reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "read", + "test_case_id": "nr_special_chars", + "sheet": "named_ranges", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: tablib does not implement named range reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + }, + "write": { + "passed": false, + "expected": { + "name": "_my_range", + "scope": "workbook", + "refers_to": "named_ranges!$B$7" + }, + "actual": { + "error": "tablib does not implement named range writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "named_ranges", + "operation": "write", + "test_case_id": "nr_special_chars", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement named range writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Named range: underscore name" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "tbl_basic": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: basic 3-col" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: with totals row" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: no style" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: single column" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: header only (no data rows)" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: with autoFilter" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "tbl_basic": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "xlsxwriter does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_basic", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "xlsxwriter does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_with_totals", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "xlsxwriter does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_no_style", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "xlsxwriter does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_col", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "xlsxwriter does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_row", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "xlsxwriter does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_autofilter", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "tbl_basic": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "python-calamine does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_basic", + "sheet": "tables", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "python-calamine does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_with_totals", + "sheet": "tables", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "python-calamine does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_no_style", + "sheet": "tables", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "python-calamine does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_col", + "sheet": "tables", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "python-calamine does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_row", + "sheet": "tables", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "python-calamine does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_autofilter", + "sheet": "tables", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "aspose-cells-foss", + "scores": { + "read": 1, + "write": 1 + }, + "test_cases": { + "tbl_basic": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: basic 3-col" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": false, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 0 + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_with_totals", + "sheet": "tables", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': True, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 1}}, actual={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': False, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 0}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": false, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 0 + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_with_totals", + "sheet": "tables", + "cell": "B3" + }, + "adapter_message": "Expected values did not match actual values: expected={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': True, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 1}}, actual={'table': {'name': 'Summary', 'ref': 'E7:G11', 'header_row': True, 'totals_row': False, 'style': 'TableStyleLight1', 'columns': ['Item', 'Count', 'Total'], 'totals_row_count': 0}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Key", + "Value" + ] + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_no_style", + "sheet": "tables", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'table': {'name': 'PlainTable', 'ref': 'E13:F16', 'header_row': True, 'totals_row': False, 'style': None, 'columns': ['Key', 'Value']}}, actual={'table': {'name': 'PlainTable', 'ref': 'E13:F16', 'header_row': True, 'totals_row': False, 'style': 'TableStyleMedium2', 'columns': ['Key', 'Value']}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Table: no style" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Key", + "Value" + ] + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_no_style", + "sheet": "tables", + "cell": "B4" + }, + "adapter_message": "Expected values did not match actual values: expected={'table': {'name': 'PlainTable', 'ref': 'E13:F16', 'header_row': True, 'totals_row': False, 'style': None, 'columns': ['Key', 'Value']}}, actual={'table': {'name': 'PlainTable', 'ref': 'E13:F16', 'header_row': True, 'totals_row': False, 'style': 'TableStyleMedium2', 'columns': ['Key', 'Value']}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: single column" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: header only (no data rows)" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: with autoFilter" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "tbl_basic": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: basic 3-col" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: with totals row" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: no style" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: single column" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: header only (no data rows)" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "read": { + "passed": true, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: with autoFilter" + }, + "write": { + "passed": true, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "tbl_basic": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_basic", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "pylightxl does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_basic", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_with_totals", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "pylightxl does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_with_totals", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_no_style", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "basic", + "label": "Table: no style" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "pylightxl does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_no_style", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_col", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Table: single column" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "pylightxl does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_col", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_row", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "pylightxl does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_row", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_autofilter", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "style_drift", + "suggested_next_step": "inspect styles.xml and the adapter's style mapping", + "explanation": { + "code": "style_drift", + "summary": "cell style metadata changed", + "probable_cause": "formatting was dropped, defaulted, or normalized differently", + "next_step": "inspect styles.xml and the adapter's style mapping", + "tag": "style" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "pylightxl does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_autofilter", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "tables", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "tbl_basic": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "pyexcel does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_basic", + "sheet": "tables", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "pyexcel does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_basic", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "pyexcel does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_with_totals", + "sheet": "tables", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "pyexcel does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_with_totals", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "pyexcel does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_no_style", + "sheet": "tables", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "pyexcel does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_no_style", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "pyexcel does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_col", + "sheet": "tables", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "pyexcel does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_col", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "pyexcel does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_row", + "sheet": "tables", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "pyexcel does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_row", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "pyexcel does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_autofilter", + "sheet": "tables", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "pyexcel does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_autofilter", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "tbl_basic": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "xlwt does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_basic", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "xlwt does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_with_totals", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "xlwt does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_no_style", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "xlwt does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_col", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "xlwt does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_row", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "xlwt does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_autofilter", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "tbl_basic": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "pandas does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_basic", + "sheet": "tables", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pandas does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "pandas does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_basic", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "pandas does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_with_totals", + "sheet": "tables", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: pandas does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "pandas does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_with_totals", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "pandas does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_no_style", + "sheet": "tables", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: pandas does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "pandas does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_no_style", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "pandas does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_col", + "sheet": "tables", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: pandas does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "pandas does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_col", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "pandas does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_row", + "sheet": "tables", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: pandas does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "pandas does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_row", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "pandas does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_autofilter", + "sheet": "tables", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: pandas does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "pandas does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_autofilter", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "tbl_basic": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_basic", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_with_totals", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_no_style", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_col", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_row", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "write": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_autofilter", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "tbl_basic": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "openpyxl-readonly does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_basic", + "sheet": "tables", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "openpyxl-readonly does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_with_totals", + "sheet": "tables", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "openpyxl-readonly does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_no_style", + "sheet": "tables", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "openpyxl-readonly does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_col", + "sheet": "tables", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "openpyxl-readonly does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_row", + "sheet": "tables", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "openpyxl-readonly does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_autofilter", + "sheet": "tables", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "tbl_basic": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "polars does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_basic", + "sheet": "tables", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: polars does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "polars does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_with_totals", + "sheet": "tables", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: polars does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "polars does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_no_style", + "sheet": "tables", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: polars does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "polars does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_col", + "sheet": "tables", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: polars does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "polars does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_row", + "sheet": "tables", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: polars does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "polars does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_autofilter", + "sheet": "tables", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: polars does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "tables", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "tbl_basic": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "tablib does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_basic", + "sheet": "tables", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: tablib does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "SalesData", + "ref": "E2:G5", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Name", + "Qty", + "Price" + ] + } + }, + "actual": { + "error": "tablib does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_basic", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: basic 3-col" + } + }, + "tbl_with_totals": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "tablib does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_with_totals", + "sheet": "tables", + "cell": "B3" + }, + "adapter_message": "NotImplementedError: tablib does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "Summary", + "ref": "E7:G11", + "header_row": true, + "totals_row": true, + "style": "TableStyleLight1", + "columns": [ + "Item", + "Count", + "Total" + ], + "totals_row_count": 1 + } + }, + "actual": { + "error": "tablib does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_with_totals", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: with totals row" + } + }, + "tbl_no_style": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "tablib does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_no_style", + "sheet": "tables", + "cell": "B4" + }, + "adapter_message": "NotImplementedError: tablib does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "PlainTable", + "ref": "E13:F16", + "header_row": true, + "totals_row": false, + "style": null, + "columns": [ + "Key", + "Value" + ] + } + }, + "actual": { + "error": "tablib does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_no_style", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Table: no style" + } + }, + "tbl_single_col": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "tablib does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_col", + "sheet": "tables", + "cell": "B5" + }, + "adapter_message": "NotImplementedError: tablib does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "SingleCol", + "ref": "E18:E21", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium2", + "columns": [ + "Score" + ] + } + }, + "actual": { + "error": "tablib does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_col", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: single column" + } + }, + "tbl_single_row": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "tablib does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_single_row", + "sheet": "tables", + "cell": "B6" + }, + "adapter_message": "NotImplementedError: tablib does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "EmptyTable", + "ref": "E23:G23", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "A", + "B", + "C" + ] + } + }, + "actual": { + "error": "tablib does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_single_row", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: header only (no data rows)" + } + }, + "tbl_autofilter": { + "read": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "tablib does not implement table reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "read", + "test_case_id": "tbl_autofilter", + "sheet": "tables", + "cell": "B7" + }, + "adapter_message": "NotImplementedError: tablib does not implement table reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + }, + "write": { + "passed": false, + "expected": { + "table": { + "name": "Filtered", + "ref": "E25:G28", + "header_row": true, + "totals_row": false, + "style": "TableStyleMedium9", + "columns": [ + "Region", + "Sales", + "Year" + ], + "autofilter": true + } + }, + "actual": { + "error": "tablib does not implement table writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "tables", + "operation": "write", + "test_case_id": "tbl_autofilter", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement table writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Table: with autoFilter" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "prot_basic": { + "read": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + }, + "write": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "read": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: with password hash" + }, + "write": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "read": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Protection: granular attribute flags" + }, + "write": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "prot_basic": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "xlsxwriter does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "xlsxwriter does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "xlsxwriter does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "prot_basic": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "python-calamine does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "python-calamine does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "python-calamine does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "prot_basic": { + "read": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + }, + "write": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "read": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: with password hash" + }, + "write": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "read": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Protection: granular attribute flags" + }, + "write": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "prot_basic": { + "read": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + }, + "write": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "read": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: with password hash" + }, + "write": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "read": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Protection: granular attribute flags" + }, + "write": { + "passed": true, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "prot_basic": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "pylightxl does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "pylightxl does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "pylightxl does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "sheet_protection", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "prot_basic": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "pyexcel does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "pyexcel does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "pyexcel does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "pyexcel does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "pyexcel does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "pyexcel does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "prot_basic": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "xlwt does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "xlwt does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "xlwt does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "prot_basic": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "pandas does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pandas does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "pandas does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "pandas does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pandas does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "pandas does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "pandas does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pandas does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "pandas does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "prot_basic": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "prot_basic": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "openpyxl-readonly does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "openpyxl-readonly does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "openpyxl-readonly does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "prot_basic": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "polars does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: polars does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "polars does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: polars does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "polars does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: polars does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "sheet_protection", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "prot_basic": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "tablib does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: tablib does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "actual": { + "error": "tablib does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_basic", + "sheet": "sheet_protection_basic", + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: basic (OOXML defaults)" + } + }, + "prot_password": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "tablib does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: tablib does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "actual": { + "error": "tablib does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_password", + "sheet": "sheet_protection_password", + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Protection: with password hash" + } + }, + "prot_granular": { + "read": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "tablib does not implement sheet protection reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "read", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: tablib does not implement sheet protection reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + }, + "write": { + "passed": false, + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "actual": { + "error": "tablib does not implement sheet protection writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "sheet_protection", + "operation": "write", + "test_case_id": "prot_granular", + "sheet": "sheet_protection_granular", + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement sheet protection writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Protection: granular attribute flags" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "page_setup_landscape": { + "read": { + "passed": true, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + }, + "write": { + "passed": true, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "read": { + "passed": true, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + }, + "write": { + "passed": true, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "read": { + "passed": true, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + }, + "write": { + "passed": true, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "page_setup_landscape": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "xlsxwriter does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "xlsxwriter does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "xlsxwriter does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "page_setup_landscape": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "python-calamine does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "python-calamine does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "python-calamine does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "aspose-cells-foss", + "scores": { + "read": 1, + "write": 0 + }, + "test_cases": { + "page_setup_landscape": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": 100, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'page_setup': {'orientation': 'landscape', 'fit_to_width': 1, 'fit_to_height': None, 'scale': None, 'print_title_rows': None, 'header_center': None, 'footer_center': None}}, actual={'page_setup': {'orientation': 'landscape', 'fit_to_width': 1, 'fit_to_height': None, 'scale': 100, 'print_title_rows': None, 'header_center': None, 'footer_center': None}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "aspose-cells-foss does not support set_page_setup: aspose-cells-foss has no print-title-rows API." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support set_page_setup: aspose-cells-foss has no print-title-rows API.", + "probable_cause": "aspose-cells-foss has no print-title-rows API.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss has no print-title-rows API.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "read": { + "passed": true, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "aspose-cells-foss does not support set_page_setup: aspose-cells-foss has no print-title-rows API." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support set_page_setup: aspose-cells-foss has no print-title-rows API.", + "probable_cause": "aspose-cells-foss has no print-title-rows API.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss has no print-title-rows API.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 100, + "print_title_rows": null, + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'page_setup': {'orientation': None, 'fit_to_width': None, 'fit_to_height': None, 'scale': None, 'print_title_rows': '$1:$2', 'header_center': 'ExcelBench Report', 'footer_center': 'Page &P'}}, actual={'page_setup': {'orientation': 'portrait', 'fit_to_width': None, 'fit_to_height': None, 'scale': 100, 'print_title_rows': None, 'header_center': 'ExcelBench Report', 'footer_center': 'Page &P'}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "aspose-cells-foss does not support set_page_setup: aspose-cells-foss has no print-title-rows API." + }, + "notes": "Write failed: UnsupportedAdapterOperationError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": null + }, + "adapter_message": "UnsupportedAdapterOperationError: aspose-cells-foss does not support set_page_setup: aspose-cells-foss has no print-title-rows API.", + "probable_cause": "aspose-cells-foss has no print-title-rows API.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "aspose-cells-foss has no print-title-rows API.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 2 + }, + "test_cases": { + "page_setup_landscape": { + "read": { + "passed": true, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + }, + "write": { + "passed": true, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "read": { + "passed": true, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + }, + "write": { + "passed": true, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "read": { + "passed": true, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "notes": "Incorrect result", + "diagnostics": [ + { + "category": "data_mismatch", + "severity": "error", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": "B2" + }, + "adapter_message": "Expected values did not match actual values: expected={'page_setup': {'orientation': None, 'fit_to_width': None, 'fit_to_height': None, 'scale': None, 'print_title_rows': '$1:$2', 'header_center': 'ExcelBench Report', 'footer_center': 'Page &P'}}, actual={'page_setup': {'orientation': None, 'fit_to_width': None, 'fit_to_height': None, 'scale': None, 'print_title_rows': None, 'header_center': 'ExcelBench Report', 'footer_center': 'Page &P'}}", + "probable_cause": "Adapter returned a value that differs from benchmark expectations.", + "root_cause_code": null, + "suggested_next_step": null, + "explanation": null + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "page_setup_landscape": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "pylightxl does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "pylightxl does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "exception", + "suggested_next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "explanation": { + "code": "exception", + "summary": "adapter raised instead of returning comparable workbook data", + "probable_cause": "adapter/runtime error interrupted the assertion path", + "next_step": "open the diagnostic adapter message and reproduce the adapter call directly", + "tag": "exception" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "pylightxl does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "page_setup", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "page_setup_landscape": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "pyexcel does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "pyexcel does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "pyexcel does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "pyexcel does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "pyexcel does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "pyexcel does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "page_setup_landscape": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "xlwt does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "xlwt does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "xlwt does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "page_setup_landscape": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "pandas does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pandas does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "pandas does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "pandas does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pandas does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "pandas does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "pandas does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pandas does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "pandas does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "page_setup_landscape": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "xlsxwriter-constmem does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "page_setup_landscape": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "openpyxl-readonly does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "openpyxl-readonly does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "openpyxl-readonly does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "page_setup_landscape": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "polars does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: polars does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "polars does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: polars does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "polars does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: polars does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "page_setup", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "page_setup_landscape": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "tablib does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: tablib does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "tablib does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_landscape", + "sheet": "page_setup_landscape", + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: landscape + fit-to-width" + } + }, + "page_setup_scale": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "tablib does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: tablib does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "actual": { + "error": "tablib does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_scale", + "sheet": "page_setup_scale", + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Page setup: portrait at 75% scale" + } + }, + "page_setup_titles": { + "read": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "tablib does not implement page setup reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "read", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: tablib does not implement page setup reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + }, + "write": { + "passed": false, + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "actual": { + "error": "tablib does not implement page setup writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "page_setup", + "operation": "write", + "test_case_id": "page_setup_titles", + "sheet": "page_setup_titles", + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement page setup writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Page setup: print titles + header/footer" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "openpyxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "chart_bar": { + "read": { + "passed": true, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + }, + "write": { + "passed": true, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "read": { + "passed": true, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + }, + "write": { + "passed": true, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "xlsxwriter", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "chart_bar": { + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "xlsxwriter does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "xlsxwriter does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_line", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "python-calamine", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "chart_bar": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "python-calamine does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_bar", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "python-calamine does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_line", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: python-calamine does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "aspose-cells-foss", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "chart_bar": { + "read": { + "passed": true, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + }, + "write": { + "passed": true, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "read": { + "passed": true, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + }, + "write": { + "passed": true, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "wolfxl", + "scores": { + "read": 3, + "write": 3 + }, + "test_cases": { + "chart_bar": { + "read": { + "passed": true, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + }, + "write": { + "passed": true, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "read": { + "passed": true, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + }, + "write": { + "passed": true, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12" + }, + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12" + } + ] + }, + "notes": null, + "diagnostics": [], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "pylightxl", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "chart_bar": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + }, + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "pylightxl does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "expected string or bytes-like object, got 'NoneType'" + }, + "notes": "Failed to open workbook", + "diagnostics": [ + { + "category": "invalid_input", + "severity": "error", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_line", + "sheet": null, + "cell": null + }, + "adapter_message": "TypeError: expected string or bytes-like object, got 'NoneType'", + "probable_cause": "Input workbook could not be opened by this adapter.", + "root_cause_code": "drawing_or_image_drift", + "suggested_next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "explanation": { + "code": "drawing_or_image_drift", + "summary": "image or drawing relationship changed", + "probable_cause": "media part may exist but worksheet drawing rels or anchors do not match", + "next_step": "inspect drawing XML, drawing rels, and xl/media package parts", + "tag": "drawing" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + }, + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "pylightxl does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_line", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pylightxl does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "xlrd", + "scores": { + "read": null, + "write": null + }, + "test_cases": {}, + "notes": "Not applicable: xlrd does not support .xlsx input" + }, + { + "feature": "chart_anchor", + "library": "pyexcel", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "chart_bar": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "pyexcel does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_bar", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + }, + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "pyexcel does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "pyexcel does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_line", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pyexcel does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + }, + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "pyexcel does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_line", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pyexcel does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "xlwt", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "chart_bar": { + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "xlwt does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "xlwt does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_line", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlwt does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "pandas", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "chart_bar": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "pandas does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_bar", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pandas does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + }, + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "pandas does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "pandas does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_line", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: pandas does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + }, + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "pandas does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_line", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: pandas does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "xlsxwriter-constmem", + "scores": { + "read": null, + "write": 0 + }, + "test_cases": { + "chart_bar": { + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "xlsxwriter-constmem does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "xlsxwriter-constmem does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_line", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: xlsxwriter-constmem does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "openpyxl-readonly", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "chart_bar": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "openpyxl-readonly does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_bar", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "openpyxl-readonly does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_line", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: openpyxl-readonly does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "polars", + "scores": { + "read": 0, + "write": null + }, + "test_cases": { + "chart_bar": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "polars does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_bar", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: polars does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "polars does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_line", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: polars does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + }, + { + "feature": "chart_anchor", + "library": "tablib", + "scores": { + "read": 0, + "write": 0 + }, + "test_cases": { + "chart_bar": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "tablib does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_bar", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: tablib does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + }, + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "tablib does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_bar", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "basic", + "label": "Chart: bar with twoCell anchor" + } + }, + "chart_line": { + "read": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "tablib does not implement chart anchor reads" + }, + "notes": "Exception: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "read", + "test_case_id": "chart_line", + "sheet": "chart_anchor", + "cell": "B2" + }, + "adapter_message": "NotImplementedError: tablib does not implement chart anchor reads", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter raised an exception while evaluating this test case.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + }, + "write": { + "passed": false, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "actual": { + "error": "tablib does not implement chart anchor writes" + }, + "notes": "Write failed: NotImplementedError", + "diagnostics": [ + { + "category": "unsupported_feature", + "severity": "warning", + "location": { + "feature": "chart_anchor", + "operation": "write", + "test_case_id": "chart_line", + "sheet": null, + "cell": null + }, + "adapter_message": "NotImplementedError: tablib does not implement chart anchor writes", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "root_cause_code": "unsupported_feature", + "suggested_next_step": "treat as unsupported capability, not a semantic regression", + "explanation": { + "code": "unsupported_feature", + "summary": "adapter reported this operation as unsupported", + "probable_cause": "Adapter could not create or save a workbook for this feature.", + "next_step": "treat as unsupported capability, not a semantic regression", + "tag": "unsupported" + } + } + ], + "importance": "edge", + "label": "Chart: line with twoCell anchor" + } + } + }, + "notes": null + } + ] +} \ No newline at end of file diff --git a/scripts/build_calc_fixture.py b/scripts/build_calc_fixture.py new file mode 100755 index 0000000..ad7f99b --- /dev/null +++ b/scripts/build_calc_fixture.py @@ -0,0 +1,286 @@ +#!/usr/bin/env python3 +"""Build the deterministic Formula Recalculation benchmark fixture. + +The canonical fixture is written by openpyxl and ships formulas with NO cached +values. LibreOffice's isolated, headless ``--convert-to xlsx`` path recalculates +a throwaway copy; every formula cache in that copy is verified before the +oracle JSON is written. Engines are scored against the oracle, so a passing +engine must produce the values itself rather than pass stored caches through. +""" + +from __future__ import annotations + +import json +import tempfile +from datetime import date, datetime +from pathlib import Path +from typing import Any + +from openpyxl import Workbook, load_workbook +from openpyxl.utils.datetime import to_excel + +from excelbench.harness.calc import libreoffice_version, recalculate_with_libreoffice + +REPOSITORY_ROOT = Path(__file__).resolve().parents[1] +DEFAULT_FIXTURE_PATH = REPOSITORY_ROOT / "fixtures" / "calc" / "financial_model.xlsx" +DEFAULT_EXPECTED_PATH = REPOSITORY_ROOT / "fixtures" / "calc" / "expected_values.json" + + +def build_fixture( + fixture_path: Path = DEFAULT_FIXTURE_PATH, + expected_path: Path = DEFAULT_EXPECTED_PATH, +) -> dict[str, Any]: + """Build a cache-free workbook, derive oracle values via LibreOffice, persist both. + + The canonical fixture keeps NO cached formula values: openpyxl writes the + formulas only. Expected values are harvested from a throwaway LibreOffice + recalculation copy. A passing engine must therefore produce the numbers + itself; passthrough of precomputed caches cannot score. + """ + fixture_path.parent.mkdir(parents=True, exist_ok=True) + workbook = _build_workbook() + workbook.save(fixture_path) + + formula_references = _formula_references(fixture_path) + with tempfile.TemporaryDirectory(prefix="excelbench-calc-oracle-") as temporary_dir: + recalculated_path = Path(temporary_dir) / "recalculated.xlsx" + recalculate_reason = recalculate_with_libreoffice( + fixture_path, recalculated_path + ) + if recalculate_reason is not None: + raise RuntimeError(recalculate_reason) + cells = _cached_cells(recalculated_path, formula_references) + _assert_fixture_cache_free(fixture_path, formula_references) + + expected = { + "oracle": f"libreoffice/{libreoffice_version() or 'unknown'}", + "cells": cells, + } + expected_path.parent.mkdir(parents=True, exist_ok=True) + expected_path.write_text(json.dumps(expected, indent=2, sort_keys=True) + "\n") + return expected + + +def _assert_fixture_cache_free( + fixture_path: Path, formula_references: list[str] +) -> None: + """Fail loudly if the canonical fixture ever ships cached formula values.""" + workbook = load_workbook(fixture_path, data_only=True, read_only=True) + try: + cached = [ + reference + for reference in formula_references + if workbook[reference.split("!", maxsplit=1)[0]][ + reference.split("!", maxsplit=1)[1] + ].value + is not None + ] + finally: + workbook.close() + if cached: + sample = ", ".join(sorted(cached)[:5]) + raise RuntimeError( + f"fixture must not ship cached formula values (found: {sample})" + ) + + +def _build_workbook() -> Workbook: + workbook = Workbook() + inputs = workbook.active + inputs.title = "Inputs" + schedule = workbook.create_sheet("Schedule") + summary = workbook.create_sheet("Summary") + _populate_inputs(inputs) + _populate_schedule(schedule) + _populate_summary(summary) + return workbook + + +def _populate_inputs(worksheet: Any) -> None: + worksheet["A1"] = "Financial model assumptions" + assumptions: list[tuple[str, Any]] = [ + ("Start Date", date(2025, 1, 31)), + ("Revenue Growth", 0.045), + ("Gross Margin", 0.62), + ("Fixed Costs", 12000.0), + ("Tax Rate", 0.24), + ("Discount Rate", 0.1), + ("Target Category", "Enterprise"), + ("Target Region", "West"), + ] + for row_index, (label, value) in enumerate(assumptions, start=2): + worksheet.cell(row=row_index, column=1, value=label) + worksheet.cell(row=row_index, column=2, value=value) + worksheet["B2"].number_format = "yyyy-mm-dd" + worksheet["B3"].number_format = "0.0%" + worksheet["B4"].number_format = "0.0%" + worksheet["B6"].number_format = "0.0%" + worksheet["B7"].number_format = "0.0%" + + headers = ["Record", "Category", "Units", "Price", "Launch Date", "Region"] + for column_index, header in enumerate(headers, start=1): + worksheet.cell(row=12, column=column_index, value=header) + categories = ("Enterprise", "SMB", "Consumer", "Enterprise", "SMB") + regions = ("West", "East", "South", "North") + for offset in range(40): + row_index = offset + 13 + worksheet.cell(row=row_index, column=1, value=offset + 1) + worksheet.cell( + row=row_index, column=2, value=categories[offset % len(categories)] + ) + worksheet.cell(row=row_index, column=3, value=20 + ((offset * 7) % 35)) + worksheet.cell( + row=row_index, column=4, value=125.0 + ((offset * 13) % 170) + 0.25 + ) + worksheet.cell(row=row_index, column=5, value=date(2025, (offset % 12) + 1, 1)) + worksheet.cell(row=row_index, column=6, value=regions[offset % len(regions)]) + + +def _populate_schedule(worksheet: Any) -> None: + worksheet["A1"] = "Metric" + for period in range(1, 13): + worksheet.cell(row=1, column=period + 1, value=period) + labels = [ + "Revenue", + "Cost of Goods Sold", + "Gross Profit", + "Fixed Costs", + "Target Units", + "Target Regional Price", + "Operating Costs", + "EBITDA", + "Tax", + "Cash Flow", + ] + for row_index, label in enumerate(labels, start=2): + worksheet.cell(row=row_index, column=1, value=label) + for column_index in range(2, 14): + column_letter = worksheet.cell(row=1, column=column_index).column_letter + formulas = { + 2: f"=100000*(1+Inputs!$B$3)^({column_letter}$1-1)", + 3: f"={column_letter}2*(1-Inputs!$B$4)", + 4: f"={column_letter}2-{column_letter}3", + 5: "=Inputs!$B$5", + 6: "=SUMIF(Inputs!$B$13:$B$52,Inputs!$B$8,Inputs!$C$13:$C$52)", + 7: "=SUMIFS(Inputs!$D$13:$D$52,Inputs!$B$13:$B$52,Inputs!$B$8," + "Inputs!$F$13:$F$52,Inputs!$B$9)", + 8: f"={column_letter}3+{column_letter}5+{column_letter}6*{column_letter}7+SUM(0)", + 9: f"={column_letter}2-{column_letter}8", + 10: f"=IF({column_letter}9>0,{column_letter}9*Inputs!$B$6,0)", + 11: f"={column_letter}9-{column_letter}10-{column_letter}2*0.08", + } + for row_index, formula in formulas.items(): + worksheet.cell(row=row_index, column=column_index, value=formula) + + +def _populate_summary(worksheet: Any) -> None: + worksheet["A1"] = "Summary Metric" + worksheet["B1"] = "Value" + formulas = { + "A2": "Positive cash flow flag", + "B2": "=IF(SUM(Schedule!B11:M11)>0,1,0)", + "A3": "Growth tier", + "B3": "=IF(Inputs!$B$3>=0.05,3,IF(Inputs!$B$3>=0.03,2,1))", + "A4": "Minimum EBITDA", + "B4": "=MIN(Schedule!B9:M9)", + "A5": "Maximum EBITDA", + "B5": "=MAX(Schedule!B9:M9)", + "A6": "Average cash flow", + "B6": "=ROUND(AVERAGE(Schedule!B11:M11),2)", + "A7": "VLOOKUP enterprise units", + "B7": '=VLOOKUP("Enterprise",Inputs!$B$13:$D$52,2,FALSE)', + "A8": "INDEX/MATCH enterprise price", + "B8": '=INDEX(Inputs!$D$13:$D$52,MATCH("Enterprise",Inputs!$B$13:$B$52,0))', + "A10": "Net present value", + "B10": "=NPV(Inputs!$B$7,Schedule!B11:M11)", + "A11": "Internal rate of return", + "B11": "=IRR(B18:N18)", + "A12": "Date plus three months", + "B12": "=EDATE(Inputs!$B$2,3)", + "A13": "Month end plus three months", + "B13": "=EOMONTH(Inputs!$B$2,3)", + "A14": "Enterprise records", + "B14": '=COUNTIF(Inputs!$B$13:$B$52,"Enterprise")', + "A15": "Enterprise west records", + "B15": '=COUNTIFS(Inputs!$B$13:$B$52,"Enterprise",Inputs!$F$13:$F$52,"West")', + } + for reference, value in formulas.items(): + worksheet[reference] = value + + worksheet["A17"] = "Signed cash-flow series for IRR" + cash_flows = [ + -100000.0, + 16500.0, + 18000.0, + 20500.0, + 23000.0, + 25000.0, + 27000.0, + 29500.0, + 31500.0, + 34000.0, + 36000.0, + 38500.0, + 41000.0, + ] + for column_index, cash_flow in enumerate(cash_flows, start=2): + worksheet.cell(row=18, column=column_index, value=cash_flow) + + +def _formula_references(fixture_path: Path) -> list[str]: + workbook = load_workbook(fixture_path, data_only=False, read_only=True) + try: + return [ + f"{worksheet.title}!{cell.coordinate}" + for worksheet in workbook.worksheets + for row in worksheet.iter_rows() + for cell in row + if isinstance(cell.value, str) and cell.value.startswith("=") + ] + finally: + workbook.close() + + +def _cached_cells( + fixture_path: Path, formula_references: list[str] +) -> dict[str, dict[str, Any]]: + workbook = load_workbook(fixture_path, data_only=True, read_only=True) + try: + cells: dict[str, dict[str, Any]] = {} + for reference in formula_references: + sheet_name, cell_reference = reference.split("!", maxsplit=1) + value = workbook[sheet_name][cell_reference].value + if value is None: + raise RuntimeError( + f"LibreOffice left an empty cached formula value at {reference}" + ) + cells[reference] = _expected_cell(value) + return cells + finally: + workbook.close() + + +def _expected_cell(value: Any) -> dict[str, Any]: + if isinstance(value, bool): + return {"value": value, "type": "bool"} + if isinstance(value, (int, float)): + return {"value": round(float(value), 10), "type": "number"} + if isinstance(value, (date, datetime)): + return {"value": round(float(to_excel(value)), 10), "type": "number"} + if isinstance(value, str): + return {"value": value, "type": "string"} + raise TypeError(f"Unsupported cached formula value: {value!r}") + + +def main() -> int: + """Build the fixture and report formula coverage with representative values.""" + expected = build_fixture() + cells = expected["cells"] + print(f"Formula cells: {len(cells)}") + for reference in sorted(cells)[:3]: + print(f"{reference}: {cells[reference]}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/build_mutation_template.py b/scripts/build_mutation_template.py new file mode 100755 index 0000000..7080755 --- /dev/null +++ b/scripts/build_mutation_template.py @@ -0,0 +1,293 @@ +#!/usr/bin/env python3 +"""Build the deterministic mutation-fidelity workbook fixture.""" + +from __future__ import annotations + +import hashlib +import json +import tempfile +import xml.etree.ElementTree as ET +from pathlib import Path +from zipfile import ZIP_DEFLATED, ZipFile, ZipInfo + +from openpyxl import Workbook +from openpyxl.chart import BarChart, LineChart, Reference +from openpyxl.comments import Comment +from openpyxl.drawing.spreadsheet_drawing import AnchorMarker, TwoCellAnchor +from openpyxl.formatting.rule import CellIsRule, ColorScaleRule +from openpyxl.styles import Font, PatternFill +from openpyxl.utils import get_column_letter +from openpyxl.workbook.defined_name import DefinedName +from openpyxl.worksheet.datavalidation import DataValidation +from openpyxl.worksheet.table import Table, TableStyleInfo + +REPO_ROOT = Path(__file__).resolve().parents[1] +FIXTURE_DIR = REPO_ROOT / "fixtures" / "mutation" +FIXTURE_PATH = FIXTURE_DIR / "template_corporate_model.xlsx" +MANIFEST_PATH = FIXTURE_DIR / "manifest.json" +FIXED_TIMESTAMP = (2026, 1, 1, 0, 0, 0) +GENERATED_AT = "2026-01-01T00:00:00Z" +_CONTENT_TYPES_NS = "http://schemas.openxmlformats.org/package/2006/content-types" +_RELATIONSHIPS_NS = "http://schemas.openxmlformats.org/package/2006/relationships" +_OFFICE_DOCUMENT_REL_NS = ( + "http://schemas.openxmlformats.org/officeDocument/2006/relationships" +) + + +def _anchor(from_cell: str, to_cell: str) -> TwoCellAnchor: + """Create the explicit two-cell anchor used by the OpenPyXL adapter.""" + from_col = ord(from_cell[0].upper()) - ord("A") + from_row = int(from_cell[1:]) - 1 + to_col = ord(to_cell[0].upper()) - ord("A") + to_row = int(to_cell[1:]) - 1 + return TwoCellAnchor( + _from=AnchorMarker(col=from_col, colOff=0, row=from_row, rowOff=0), + to=AnchorMarker(col=to_col, colOff=0, row=to_row, rowOff=0), + ) + + +def _make_workbook(path: Path) -> None: + """Build the structural workbook before custom XML injection.""" + workbook = Workbook() + inputs = workbook.active + inputs.title = "Inputs" + schedule = workbook.create_sheet("Schedule") + summary = workbook.create_sheet("Summary") + workbook.properties.created = "2026-01-01T00:00:00Z" + workbook.properties.modified = "2026-01-01T00:00:00Z" + + headers = ["Driver", "Q1", "Q2", "Q3", "Q4", "Q5", "Q6", "Q7"] + inputs.append(headers) + for row_index in range(2, 42): + inputs.cell(row_index, 1, f"Input {row_index - 1:02d}") + for column_index in range(2, 9): + inputs.cell(row_index, column_index, (row_index - 1) * column_index * 10) + for cell in inputs[1]: + cell.font = Font(bold=True, color="FFFFFF") + cell.fill = PatternFill("solid", fgColor="1F4E78") + for column_index in range(1, 9): + inputs.column_dimensions[get_column_letter(column_index)].width = 14 + inputs.freeze_panes = "B2" + inputs["A2"].hyperlink = "https://example.com/corporate-model-inputs" + inputs["A2"].comment = Comment("Mutation target workbook input.", "ExcelBench") + + inputs_table = Table(displayName="CorporateInputs", ref="A1:H41") + inputs_table.tableStyleInfo = TableStyleInfo( + name="TableStyleMedium9", + showFirstColumn=False, + showLastColumn=False, + showRowStripes=True, + showColumnStripes=False, + ) + inputs.add_table(inputs_table) + + list_validation = DataValidation( + type="list", formula1='"Low,Medium,High"', allow_blank=True + ) + list_validation.add("H2:H41") + inputs.add_data_validation(list_validation) + decimal_validation = DataValidation( + type="decimal", + operator="between", + formula1="0", + formula2="100000", + allow_blank=False, + ) + decimal_validation.add("B2:G41") + inputs.add_data_validation(decimal_validation) + inputs.conditional_formatting.add( + "B2:H41", + CellIsRule( + operator="greaterThan", + formula=["1000"], + fill=PatternFill("solid", fgColor="FFF2CC"), + ), + ) + inputs.conditional_formatting.add( + "B2:H41", + ColorScaleRule( + start_type="min", + start_color="F8696B", + mid_type="percentile", + mid_value=50, + mid_color="FFEB84", + end_type="max", + end_color="63BE7B", + ), + ) + + schedule.append(["Schedule Metric", *headers[1:]]) + for row_index in range(2, 15): + schedule.cell(row_index, 1, f"Schedule {row_index - 1:02d}") + for column_index in range(2, 9): + column_letter = get_column_letter(column_index) + input_row = row_index + 1 + if row_index == 2: + formula = f"=Inputs!{column_letter}{input_row}" + elif row_index == 3: + formula = f"=SUM({column_letter}2,Inputs!{column_letter}{input_row})" + else: + formula = f"=SUM({column_letter}2:{column_letter}{row_index - 1})" + schedule.cell(row_index, column_index, formula) + schedule.freeze_panes = "B2" + schedule.protection.sheet = True + + summary.append(["Summary Metric", *headers[1:]]) + for row_index in range(2, 12): + summary.cell(row_index, 1, f"Summary {row_index - 1:02d}") + source_row = row_index + 2 + for column_index in range(2, 9): + column_letter = get_column_letter(column_index) + summary.cell( + row_index, column_index, f"=Schedule!{column_letter}{source_row}" + ) + summary.freeze_panes = "B2" + summary.page_setup.orientation = "landscape" + summary.page_setup.fitToWidth = 1 + summary.print_title_rows = "$1:$2" + summary.oddHeader.center.text = "Quarterly Model" + + values = Reference(summary, min_col=2, max_col=8, min_row=1, max_row=11) + categories = Reference(summary, min_col=1, min_row=2, max_row=11) + bar_chart = BarChart() + bar_chart.title = "Quarterly Summary" + bar_chart.add_data(values, titles_from_data=True) + bar_chart.set_categories(categories) + bar_chart.anchor = _anchor("B2", "H12") + summary.add_chart(bar_chart) + + line_chart = LineChart() + line_chart.title = "Quarterly Trend" + line_chart.add_data(values, titles_from_data=True) + line_chart.set_categories(categories) + line_chart.anchor = _anchor("J2", "P12") + summary.add_chart(line_chart) + + workbook.defined_names.add( + DefinedName("CorporateInputs", attr_text="'Inputs'!$B$2:$H$10") + ) + workbook.defined_names.add( + DefinedName("LocalGrowthRate", attr_text="'Inputs'!$B$2", localSheetId=0) + ) + workbook.save(path) + workbook.close() + + +def _inject_custom_xml(path: Path) -> None: + """Inject package parts OpenPyXL intentionally does not preserve on save.""" + with ZipFile(path) as archive: + parts = {name: archive.read(name) for name in archive.namelist()} + + root_rels = ET.fromstring(parts["_rels/.rels"]) + ET.register_namespace("", _RELATIONSHIPS_NS) + relation_tag = f"{{{_RELATIONSHIPS_NS}}}Relationship" + if not any( + relation.get("Type") == f"{_OFFICE_DOCUMENT_REL_NS}/customXml" + for relation in root_rels + ): + existing_ids = {relation.get("Id") for relation in root_rels} + relation_id = "rId1" + suffix = 1 + while relation_id in existing_ids: + suffix += 1 + relation_id = f"rId{suffix}" + ET.SubElement( + root_rels, + relation_tag, + { + "Id": relation_id, + "Type": f"{_OFFICE_DOCUMENT_REL_NS}/customXml", + "Target": "customXml/item1.xml", + }, + ) + parts["_rels/.rels"] = ET.tostring( + root_rels, encoding="utf-8", xml_declaration=True + ) + + content_types = ET.fromstring(parts["[Content_Types].xml"]) + ET.register_namespace("", _CONTENT_TYPES_NS) + override_tag = f"{{{_CONTENT_TYPES_NS}}}Override" + required_override = "/customXml/itemProps1.xml" + if not any(item.get("PartName") == required_override for item in content_types): + ET.SubElement( + content_types, + override_tag, + { + "PartName": required_override, + "ContentType": ( + "application/vnd.openxmlformats-officedocument.customXmlProperties+xml" + ), + }, + ) + parts["[Content_Types].xml"] = ET.tostring( + content_types, encoding="utf-8", xml_declaration=True + ) + + parts["customXml/item1.xml"] = b""" + + openpyxl-targeted-fixture +""" + parts["customXml/itemProps1.xml"] = b""" + + +""" + parts[ + "customXml/_rels/item1.xml.rels" + ] = b""" + + +""" + + with ZipFile(path, "w", compression=ZIP_DEFLATED, compresslevel=9) as archive: + for name in sorted(parts): + info = ZipInfo(filename=name, date_time=FIXED_TIMESTAMP) + info.compress_type = ZIP_DEFLATED + archive.writestr(info, parts[name]) + + +def _sha256(data: bytes) -> str: + """Return a SHA-256 digest for fixture package content.""" + return hashlib.sha256(data).hexdigest() + + +def build_fixture() -> Path: + """Build the workbook and manifest, returning the workbook path.""" + FIXTURE_DIR.mkdir(parents=True, exist_ok=True) + with tempfile.NamedTemporaryFile( + suffix=".xlsx", dir=FIXTURE_DIR, delete=False + ) as temporary: + staging_path = Path(temporary.name) + try: + _make_workbook(staging_path) + _inject_custom_xml(staging_path) + staging_path.replace(FIXTURE_PATH) + finally: + staging_path.unlink(missing_ok=True) + + with ZipFile(FIXTURE_PATH) as archive: + part_names = sorted(archive.namelist()) + checksums = {name: _sha256(archive.read(name)) for name in part_names} + manifest = { + "generated_at": GENERATED_AT, + "generator": "openpyxl-structural+customxml-injection", + "parts": part_names, + "checksums": checksums, + "mutation": {"sheet": "Inputs", "cell": "B2", "value": "MUTATED-"}, + "second_mutation": {"sheet": "Inputs", "cell": "C3", "value": 1337}, + } + MANIFEST_PATH.write_text( + json.dumps(manifest, indent=2, sort_keys=True) + "\n", encoding="utf-8" + ) + return FIXTURE_PATH + + +def main() -> None: + """Build the committed mutation fixture.""" + print(build_fixture()) + + +if __name__ == "__main__": + main() diff --git a/scripts/build_tier4_fixtures.py b/scripts/build_tier4_fixtures.py new file mode 100755 index 0000000..4bf7670 --- /dev/null +++ b/scripts/build_tier4_fixtures.py @@ -0,0 +1,286 @@ +#!/usr/bin/env python3 +"""Build Tier-4 structural fixtures: sheet_protection, page_setup, chart_anchor. + +No Excel application is involved: workbooks are constructed with openpyxl +through OpenpyxlAdapter's Tier-4 methods, and every manifest expectation is +recorded from the post-save readback, so expectations always equal roundtrip +reality. + +Outputs under (default: fixtures/excel): + tier4/20_sheet_protection.xlsx + tier4/21_page_setup.xlsx + tier4/22_chart_anchor.xlsx + tier4_manifest_fragment.json (to be merged into manifest.json) +""" + +from __future__ import annotations + +import json +import sys +from datetime import UTC, datetime +from pathlib import Path +from typing import Any + +from excelbench.harness.adapters.openpyxl_adapter import OpenpyxlAdapter +from excelbench.models import CellType, CellValue + +REPO_ROOT = Path(__file__).resolve().parent.parent +DEFAULT_FIXTURES_ROOT = REPO_ROOT / "fixtures" / "excel" +TIER4_DIR = "tier4" +GENERATOR = "openpyxl-structural" +GENERATOR_VERSION = "0.1.0" + +JSONDict = dict[str, Any] + +PROTECTION_CASES: list[JSONDict] = [ + { + "sheet": "sheet_protection_basic", + "id": "prot_basic", + "label": "Protection: basic (OOXML defaults)", + "importance": "basic", + "settings": {"protected": True}, + }, + { + "sheet": "sheet_protection_password", + "id": "prot_password", + "label": "Protection: with password hash", + "importance": "basic", + "settings": {"protected": True, "password": "bench-secret"}, + }, + { + "sheet": "sheet_protection_granular", + "id": "prot_granular", + "label": "Protection: granular attribute flags", + "importance": "edge", + "settings": { + "protected": True, + "format_cells": False, + "insert_rows": True, + "select_locked_cells": True, + "sort": False, + "auto_filter": True, + }, + }, +] + +PAGE_SETUP_CASES: list[JSONDict] = [ + { + "sheet": "page_setup_landscape", + "id": "page_setup_landscape", + "label": "Page setup: landscape + fit-to-width", + "importance": "basic", + "settings": {"orientation": "landscape", "fit_to_width": 1}, + }, + { + "sheet": "page_setup_scale", + "id": "page_setup_scale", + "label": "Page setup: portrait at 75% scale", + "importance": "basic", + "settings": {"orientation": "portrait", "scale": 75}, + }, + { + "sheet": "page_setup_titles", + "id": "page_setup_titles", + "label": "Page setup: print titles + header/footer", + "importance": "edge", + "settings": { + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P", + }, + }, +] + +CHART_DATA_NUMBERS = [12, 25, 18, 31, 22, 40, 29] # E2:E8 +CHART_DATA_LABELS = ["Q1", "Q2", "Q3", "Q4", "Q5", "Q6", "Q7"] # F2:F8 + +CHART_CASES: list[JSONDict] = [ + { + "id": "chart_bar", + "label": "Chart: bar with twoCell anchor", + "importance": "basic", + "chart": { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8", + }, + }, + { + "id": "chart_line", + "label": "Chart: line with twoCell anchor", + "importance": "edge", + "chart": { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8", + }, + }, +] + + +def build_sheet_protection(adapter: OpenpyxlAdapter, out_dir: Path) -> JSONDict: + """Build 20_sheet_protection.xlsx and return its manifest entry.""" + path = out_dir / "20_sheet_protection.xlsx" + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "sheet_protection") + for case in PROTECTION_CASES: + adapter.add_sheet(workbook, case["sheet"]) + for case in PROTECTION_CASES: + adapter.set_sheet_protection(workbook, case["sheet"], case["settings"]) + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + try: + test_cases = [] + for case in PROTECTION_CASES: + expected = dict(adapter.read_sheet_protection(reopened, case["sheet"])) + password = case["settings"].get("password") + if password is not None: + expected["password"] = password + test_cases.append(_test_case(case, {"protection": expected})) + finally: + adapter.close_workbook(reopened) + return _manifest_entry(path.name, "sheet_protection", test_cases) + + +def build_page_setup(adapter: OpenpyxlAdapter, out_dir: Path) -> JSONDict: + """Build 21_page_setup.xlsx and return its manifest entry.""" + path = out_dir / "21_page_setup.xlsx" + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "page_setup") + for case in PAGE_SETUP_CASES: + adapter.add_sheet(workbook, case["sheet"]) + for case in PAGE_SETUP_CASES: + adapter.set_page_setup(workbook, case["sheet"], case["settings"]) + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + try: + test_cases = [ + _test_case( + case, {"page_setup": adapter.read_page_setup(reopened, case["sheet"])} + ) + for case in PAGE_SETUP_CASES + ] + finally: + adapter.close_workbook(reopened) + return _manifest_entry(path.name, "page_setup", test_cases) + + +def build_chart_anchor(adapter: OpenpyxlAdapter, out_dir: Path) -> JSONDict: + """Build 22_chart_anchor.xlsx and return its manifest entry.""" + path = out_dir / "22_chart_anchor.xlsx" + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "chart_anchor") + for offset, value in enumerate(CHART_DATA_NUMBERS): + adapter.write_cell_value( + workbook, + "chart_anchor", + f"E{2 + offset}", + CellValue(type=CellType.NUMBER, value=value), + ) + for offset, label in enumerate(CHART_DATA_LABELS): + adapter.write_cell_value( + workbook, + "chart_anchor", + f"F{2 + offset}", + CellValue(type=CellType.STRING, value=label), + ) + for case in CHART_CASES: + adapter.add_chart_with_anchor(workbook, "chart_anchor", case["chart"]) + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + try: + charts_by_from = { + chart["from"]: chart + for chart in adapter.read_chart_anchors(reopened, "chart_anchor") + } + finally: + adapter.close_workbook(reopened) + + test_cases = [] + for case in CHART_CASES: + spec = case["chart"] + readback = charts_by_from.get(spec["from"]) + if readback is None: + raise RuntimeError(f"chart anchor readback missing for {spec['from']}") + expected = { + **readback, + "data_ref": spec["data_ref"], + "categories_ref": spec["categories_ref"], + } + test_cases.append(_test_case(case, {"charts": [expected]})) + return _manifest_entry(path.name, "chart_anchor", test_cases) + + +def _test_case(case: JSONDict, expected: JSONDict) -> JSONDict: + entry: JSONDict = { + "id": case["id"], + "label": case["label"], + "row": 2, + } + if case.get("sheet"): + entry["sheet"] = case["sheet"] + entry["expected"] = expected + entry["importance"] = case["importance"] + return entry + + +def _manifest_entry( + filename: str, feature: str, test_cases: list[JSONDict] +) -> JSONDict: + return { + "path": f"{TIER4_DIR}/{filename}", + "feature": feature, + "tier": 4, + "file_format": "xlsx", + "test_cases": test_cases, + } + + +def build_all(fixtures_root: Path = DEFAULT_FIXTURES_ROOT) -> Path: + """Build all Tier-4 fixtures plus the manifest fragment. + + Returns the path to the written fragment. + """ + out_dir = fixtures_root / TIER4_DIR + out_dir.mkdir(parents=True, exist_ok=True) + adapter = OpenpyxlAdapter() + entries = [ + build_sheet_protection(adapter, out_dir), + build_page_setup(adapter, out_dir), + build_chart_anchor(adapter, out_dir), + ] + fragment: JSONDict = { + "generated_at": datetime.now(UTC).isoformat(), + "excel_version": "none", + "generator_version": GENERATOR_VERSION, + "generator": GENERATOR, + "file_format": "xlsx", + "files": entries, + } + fragment_path = fixtures_root / "tier4_manifest_fragment.json" + with open(fragment_path, "w") as f: + json.dump(fragment, f, indent=2) + f.write("\n") + return fragment_path + + +def main(argv: list[str] | None = None) -> int: + args = sys.argv[1:] if argv is None else argv + fixtures_root = Path(args[0]).resolve() if args else DEFAULT_FIXTURES_ROOT + fragment_path = build_all(fixtures_root) + print(f"Tier-4 fixtures written to {fixtures_root / TIER4_DIR}") + print(f"Manifest fragment: {fragment_path}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/src/excelbench/cli.py b/src/excelbench/cli.py index 4c8292b..954be37 100644 --- a/src/excelbench/cli.py +++ b/src/excelbench/cli.py @@ -20,7 +20,7 @@ XLS_PROFILE_DEFAULT_TEST_DIR = Path("fixtures/excel_xls") XLSX_PROFILE_DEFAULT_TEST_DIR = Path("test_files") PERF_XLSX_PROFILE_DEFAULT_TEST_DIR = Path("fixtures/excel") -CROSS_LANGUAGE_ADAPTER_NAMES = ("apache-poi", "excelize") +CROSS_LANGUAGE_ADAPTER_NAMES = ("apache-poi", "excelize", "zavora-xlsx") @app.command() @@ -123,7 +123,10 @@ def benchmark( console.print("[red]Error: profile must be one of: xlsx, xls[/red]") raise typer.Exit(1) - if profile == "xls" and test_dir.resolve() == XLSX_PROFILE_DEFAULT_TEST_DIR.resolve(): + if ( + profile == "xls" + and test_dir.resolve() == XLSX_PROFILE_DEFAULT_TEST_DIR.resolve() + ): test_dir = XLS_PROFILE_DEFAULT_TEST_DIR # These command functions are sometimes invoked directly from tests. @@ -162,7 +165,9 @@ def benchmark( console.print() try: - results = run_benchmark(test_dir, adapters=selected, features=features, profile=profile) + results = run_benchmark( + test_dir, adapters=selected, features=features, profile=profile + ) if append_results: import json @@ -303,7 +308,10 @@ def perf( ) raise typer.Exit(1) - if profile == "xls" and test_dir.resolve() == PERF_XLSX_PROFILE_DEFAULT_TEST_DIR.resolve(): + if ( + profile == "xls" + and test_dir.resolve() == PERF_XLSX_PROFILE_DEFAULT_TEST_DIR.resolve() + ): test_dir = XLS_PROFILE_DEFAULT_TEST_DIR available = get_all_adapters() @@ -348,7 +356,9 @@ def perf( ) render_perf_results(perf_results, output_dir) - console.print(f"[green]✓ Performance results written to {output_dir}/perf[/green]") + console.print( + f"[green]✓ Performance results written to {output_dir}/perf[/green]" + ) console.print(f" - {output_dir}/perf/results.json") console.print(f" - {output_dir}/perf/README.md") console.print(f" - {output_dir}/perf/matrix.csv") @@ -390,7 +400,9 @@ def perf( ] -def _resolve_shape_features(*, types_arg: str, rows: int) -> tuple[list[str], list[str], list[str]]: +def _resolve_shape_features( + *, types_arg: str, rows: int +) -> tuple[list[str], list[str], list[str]]: """Translate --types and --rows into (read_features, write_features, tier_labels). Tiers are chosen as every label whose canonical cell-count <= ``rows``, so @@ -413,7 +425,9 @@ def _resolve_shape_features(*, types_arg: str, rows: int) -> tuple[list[str], li tier_labels = [label for label, cap in _DATA_SHAPE_TIER_CAPS if cap <= rows] if not tier_labels: - raise ValueError(f"--rows {rows} is below the smallest tier (1000); pick at least 1000.") + raise ValueError( + f"--rows {rows} is below the smallest tier (1000); pick at least 1000." + ) read_features: list[str] = [] write_features: list[str] = [] @@ -521,7 +535,9 @@ def _resolve_file_shape_features( for label, total_cells in _FILE_SHAPE_LABELS: if total_cells > rows: continue - category = next((c for c in _FILE_SHAPE_CATEGORIES if label.startswith(c)), None) + category = next( + (c for c in _FILE_SHAPE_CATEGORIES if label.startswith(c)), None + ) if category in wanted_cats: selected.append(label) @@ -579,7 +595,9 @@ def _file_shape_fixtures_stale( and isinstance(f.get("feature"), str) and f["feature"].startswith("file_shape_") and ( - "_1m" in f["feature"] or "_100x10k_" in f["feature"] or "_1000x1k_" in f["feature"] + "_1m" in f["feature"] + or "_100x10k_" in f["feature"] + or "_1000x1k_" in f["feature"] ) for f in files ): @@ -689,10 +707,14 @@ def perf_shape( needs_1m = "1m" in tier_labels manifest_path = fixtures / "manifest.json" generator_script = ( - Path(__file__).resolve().parents[2] / "scripts" / "generate_throughput_fixtures.py" + Path(__file__).resolve().parents[2] + / "scripts" + / "generate_throughput_fixtures.py" ) - if regenerate or _shape_fixtures_stale(manifest_path, generator_script, needs_1m=needs_1m): + if regenerate or _shape_fixtures_stale( + manifest_path, generator_script, needs_1m=needs_1m + ): gen_cmd = [ sys.executable, str(generator_script), @@ -875,10 +897,14 @@ def perf_file_shape( ) manifest_path = fixtures / "manifest.json" generator_script = ( - Path(__file__).resolve().parents[2] / "scripts" / "generate_throughput_fixtures.py" + Path(__file__).resolve().parents[2] + / "scripts" + / "generate_throughput_fixtures.py" ) - if regenerate or _file_shape_fixtures_stale(manifest_path, generator_script, needs_1m=needs_1m): + if regenerate or _file_shape_fixtures_stale( + manifest_path, generator_script, needs_1m=needs_1m + ): gen_cmd = [ sys.executable, str(generator_script), @@ -888,7 +914,9 @@ def perf_file_shape( ] if needs_1m: gen_cmd.append("--include-1m") - console.print(f"[bold]Generating file-shape fixtures...[/bold] {' '.join(gen_cmd)}") + console.print( + f"[bold]Generating file-shape fixtures...[/bold] {' '.join(gen_cmd)}" + ) try: subprocess.run(gen_cmd, check=True) except subprocess.CalledProcessError as e: @@ -986,7 +1014,9 @@ def generate_xls_command( table.add_column("Feature", style="magenta") table.add_column("Test Cases", justify="right", style="green") for test_file in manifest.files: - table.add_row(test_file.path, test_file.feature, str(len(test_file.test_cases))) + table.add_row( + test_file.path, test_file.feature, str(len(test_file.test_cases)) + ) console.print(table) except Exception as e: console.print(f"[red]Error: {e}[/red]") @@ -1092,7 +1122,9 @@ def roundtrip_context( "-a", help="Run only specified adapter(s) by name. Repeatable.", ), - cycles: int = typer.Option(2, "--cycles", min=1, help="Number of open/save cycles."), + cycles: int = typer.Option( + 2, "--cycles", min=1, help="Number of open/save cycles." + ), ) -> None: """Measure semantic drift after repeated workbook open/save cycles.""" from excelbench.harness.adapters import get_all_adapters @@ -1103,13 +1135,19 @@ def roundtrip_context( selected = [available[name] for name in selected_names if name in available] missing = [name for name in selected_names if name not in available] if missing: - console.print(f"[yellow]Skipping unavailable adapters: {', '.join(missing)}[/yellow]") + console.print( + f"[yellow]Skipping unavailable adapters: {', '.join(missing)}[/yellow]" + ) if not selected: console.print("[red]Error: No selected adapters are available.[/red]") raise typer.Exit(1) - results = run_roundtrip_context(test_dir, output_dir, adapters=selected, cycles=cycles) - failures = [result for result in results if not result.passed and not result.skipped] + results = run_roundtrip_context( + test_dir, output_dir, adapters=selected, cycles=cycles + ) + failures = [ + result for result in results if not result.passed and not result.skipped + ] console.print(f"[green]✓ Roundtrip context written to {output_dir}[/green]") console.print(f" - {output_dir}/roundtrip.json") console.print(f" - {output_dir}/ROUNDTRIP.md") @@ -1135,7 +1173,9 @@ def compatibility_context( from excelbench.harness.compat_cases import run_compatibility_context payload = run_compatibility_context(output_dir, adapter_names=adapters) - failures = [row for row in payload["results"] if not row["passed"] and not row["skipped"]] + failures = [ + row for row in payload["results"] if not row["passed"] and not row["skipped"] + ] console.print(f"[green]✓ Compatibility context written to {output_dir}[/green]") console.print(f" - {output_dir}/compatibility.json") console.print(f" - {output_dir}/COMPATIBILITY.md") @@ -1160,7 +1200,9 @@ def cross_language_chart_context( from excelbench.harness.artifact_context import run_chart_context payload = run_chart_context(fixture_dir, output_dir) - failures = [row for row in payload["results"] if not row["passed"] and not row["skipped"]] + failures = [ + row for row in payload["results"] if not row["passed"] and not row["skipped"] + ] console.print(f"[green]✓ Chart context written to {output_dir}[/green]") console.print(f" - {output_dir}/results.json") console.print(f" - {output_dir}/README.md") @@ -1190,8 +1232,12 @@ def macro_context( """Validate macro package preservation evidence.""" from excelbench.harness.artifact_context import run_macro_context - payload = run_macro_context(test_dir, output_dir, preserve_with_wolfxl=preserve_with_wolfxl) - failures = [row for row in payload["results"] if not row["passed"] and not row["skipped"]] + payload = run_macro_context( + test_dir, output_dir, preserve_with_wolfxl=preserve_with_wolfxl + ) + failures = [ + row for row in payload["results"] if not row["passed"] and not row["skipped"] + ] console.print(f"[green]✓ Macro context written to {output_dir}[/green]") console.print(f" - {output_dir}/results.json") console.print(f" - {output_dir}/README.md") @@ -1223,7 +1269,9 @@ def cross_language_context( from excelbench.results import render_results available = {adapter.name: adapter for adapter in get_all_adapters()} - selected = [available[name] for name in CROSS_LANGUAGE_ADAPTER_NAMES if name in available] + selected = [ + available[name] for name in CROSS_LANGUAGE_ADAPTER_NAMES if name in available + ] if not selected: console.print( @@ -1243,7 +1291,9 @@ def cross_language_context( render_results(results, output_dir) _write_cross_language_index(output_dir, [a.name for a in selected]) console.print() - console.print(f"[green]✓ Cross-language context results written to {output_dir}[/green]") + console.print( + f"[green]✓ Cross-language context results written to {output_dir}[/green]" + ) console.print(f" - {output_dir}/results.json") console.print(f" - {output_dir}/README.md") console.print(f" - {output_dir}/matrix.csv") @@ -1280,10 +1330,14 @@ def cross_language_pivot_context( output_dir.mkdir(parents=True, exist_ok=True) results = _collect_cross_language_pivot_context(fixture_path, output_dir) - (output_dir / "results.json").write_text(json.dumps(results, indent=2), encoding="utf-8") + (output_dir / "results.json").write_text( + json.dumps(results, indent=2), encoding="utf-8" + ) _write_cross_language_pivot_readme(output_dir, results) _write_cross_language_pivot_context_note(output_dir) - console.print(f"[green]✓ Cross-language pivot context written to {output_dir}[/green]") + console.print( + f"[green]✓ Cross-language pivot context written to {output_dir}[/green]" + ) console.print(f" - {output_dir}/results.json") console.print(f" - {output_dir}/README.md") console.print(f" - {output_dir}/CONTEXT.md") @@ -1348,7 +1402,9 @@ def _results_from_json(data: dict[str, Any]) -> "BenchmarkResults": severity=DiagnosticSeverity(d["severity"]), location=DiagnosticLocation( feature=d["location"]["feature"], - operation=OperationType(d["location"]["operation"]), + operation=OperationType( + d["location"]["operation"] + ), test_case_id=d["location"].get("test_case_id"), sheet=d["location"].get("sheet"), cell=d["location"].get("cell"), @@ -1379,7 +1435,11 @@ def _results_from_json(data: dict[str, Any]) -> "BenchmarkResults": actual=tc["actual"], notes=tc.get("notes"), diagnostics=[], - importance=(Importance(tc["importance"]) if tc.get("importance") else None), + importance=( + Importance(tc["importance"]) + if tc.get("importance") + else None + ), label=tc.get("label"), ) ) @@ -1468,7 +1528,9 @@ def _write_cross_language_index(output_dir: Path, adapters: list[str]) -> None: (output_dir / "CONTEXT.md").write_text(content) -def _collect_cross_language_pivot_context(fixture_path: Path, output_dir: Path) -> dict[str, Any]: +def _collect_cross_language_pivot_context( + fixture_path: Path, output_dir: Path +) -> dict[str, Any]: import platform as _platform from datetime import UTC, datetime from zipfile import ZipFile @@ -1515,7 +1577,9 @@ def _collect_cross_language_pivot_context(fixture_path: Path, output_dir: Path) ) helper_info["fixture_metadata"] = res.payload if res.passed: - helper_info["fixture_read_detects_pivot"] = _helper_detects_pivot(name, res.payload) + helper_info["fixture_read_detects_pivot"] = _helper_detects_pivot( + name, res.payload + ) else: helper_info["fixture_error"] = ( res.payload.get("message") or res.stderr or res.stdout @@ -1552,7 +1616,9 @@ def _helper_detects_pivot(helper_name: str, payload: dict[str, Any]) -> bool: sheets = payload.get("sheets") or [] return any(int(sheet.get("pivots", 0)) > 0 for sheet in sheets) counts = payload.get("counts") or {} - return any("pivot" in key.lower() and int(value) > 0 for key, value in counts.items()) + return any( + "pivot" in key.lower() and int(value) > 0 for key, value in counts.items() + ) def _run_excelize_pivot_probe(output_path: Path) -> dict[str, Any]: @@ -1617,7 +1683,9 @@ def _run_excelize_pivot_probe(output_path: Path) -> dict[str, Any]: pivot_parts: list[str] = [] with ZipFile(output_path) as zf: pivot_parts = sorted( - name for name in zf.namelist() if "pivot" in name.lower() or "cache" in name.lower() + name + for name in zf.namelist() + if "pivot" in name.lower() or "cache" in name.lower() ) verifier = OpenpyxlAdapter() wb = verifier.open_workbook(output_path) @@ -1641,7 +1709,9 @@ def _pivot_coord_to_cell(row: int, col: int) -> str: return f"{letters}{row}" -def _write_cross_language_pivot_readme(output_dir: Path, results: dict[str, Any]) -> None: +def _write_cross_language_pivot_readme( + output_dir: Path, results: dict[str, Any] +) -> None: import json fixture = results["fixture"] @@ -1664,7 +1734,8 @@ def _write_cross_language_pivot_readme(output_dir: Path, results: dict[str, Any] ] if fixture_parts: lines.extend( - ["- Fixture pivot-related parts:"] + [f" - `{part}`" for part in fixture_parts] + ["- Fixture pivot-related parts:"] + + [f" - `{part}`" for part in fixture_parts] ) else: lines.append("- Fixture pivot-related parts: none detected") @@ -1683,7 +1754,9 @@ def _write_cross_language_pivot_readme(output_dir: Path, results: dict[str, Any] "| Tool | Pivot write support | Evidence |", "|---|---:|---|", _pivot_probe_row("apache-poi", apache_probe, ""), - _pivot_probe_row("excelize", excelize_probe, "OOXML parts + openpyxl readback"), + _pivot_probe_row( + "excelize", excelize_probe, "OOXML parts + openpyxl readback" + ), ] ) if excelize_probe.get("supported"): @@ -1695,7 +1768,10 @@ def _write_cross_language_pivot_readme(output_dir: Path, results: dict[str, Any] f"- Output workbook: `{excelize_probe['output_path']}`", "- Pivot-related OOXML parts:", ] - + [f" - `{part}`" for part in excelize_probe.get("pivot_related_parts", [])] + + [ + f" - `{part}`" + for part in excelize_probe.get("pivot_related_parts", []) + ] + [ "- Openpyxl readback:", "```json\n" @@ -1726,9 +1802,13 @@ def _pivot_helper_row(helper_name: str, helpers: dict[str, Any], notes: str) -> return f"| {helper_name} | {available} | {detects} | {notes} |" -def _pivot_probe_row(tool_name: str, probe: dict[str, Any], success_evidence: str) -> str: +def _pivot_probe_row( + tool_name: str, probe: dict[str, Any], success_evidence: str +) -> str: supported = "Yes" if probe.get("supported") else "No" - evidence = success_evidence if probe.get("supported") else str(probe.get("reason", "")) + evidence = ( + success_evidence if probe.get("supported") else str(probe.get("reason", "")) + ) return f"| {tool_name} | {supported} | {evidence} |" @@ -1818,7 +1898,9 @@ def heatmap( for p in paths: console.print(f" [green]✓[/green] {p}") if not paths: - console.print("[yellow]No scored results found — nothing to render.[/yellow]") + console.print( + "[yellow]No scored results found — nothing to render.[/yellow]" + ) except Exception as e: console.print(f"[red]Error: {e}[/red]") raise typer.Exit(1) @@ -1899,7 +1981,11 @@ def html_dashboard( try: perf = perf_path if perf_path.exists() else None sdir = scatter_dir if scatter_dir.exists() else None - mem = memory_path if isinstance(memory_path, Path) and memory_path.exists() else None + mem = ( + memory_path + if isinstance(memory_path, Path) and memory_path.exists() + else None + ) render_html_dashboard(fidelity_path, perf, output_path, sdir, memory_json=mem) console.print(f" [green]✓[/green] {output_path}") except Exception as e: @@ -1952,6 +2038,110 @@ def scatter( raise typer.Exit(1) +@app.command() +def mutation( + template: Path = typer.Option( + Path("fixtures/mutation/template_corporate_model.xlsx"), + "--template", + help="Corporate-model template workbook to mutate.", + ), + output_dir: Path = typer.Option( + Path("results/mutation"), + "--output", + "-o", + help="Directory to save mutation-suite results.", + ), + repeats: int = typer.Option( + 3, + "--repeats", + help="Measured mutation runs per engine (median reported).", + ), +) -> None: + """Run the surgical template-mutation suite. + + Each engine mutates two cells in a complex corporate template; the suite + measures wall time, peak RSS, and a package-preservation score against the + original template. + """ + from excelbench.harness.mutation import run_mutation_suite + + if not template.exists(): + console.print(f"[red]Error: template not found at {template}[/red]") + raise typer.Exit(1) + console.print("[bold]Running template-mutation suite...[/bold]") + console.print(f" Template: {template}") + console.print(f" Output: {output_dir}") + console.print() + + try: + results = run_mutation_suite(template, output_dir, repeats=repeats) + from excelbench.results.mutation_renderer import render_mutation_report + + render_mutation_report(results, output_dir) + for name, engine in results["engines"].items(): + console.print( + f" {name}: {engine['status']}, " + f"{engine['wall_ms_median']}ms, preservation {engine['preservation_score']}" + ) + console.print() + console.print(f"[green]✓ Mutation results written to {output_dir}[/green]") + except Exception as e: + console.print(f"[red]Error: {e}[/red]") + raise typer.Exit(1) + + +@app.command() +def calc( + fixture: Path = typer.Option( + Path("fixtures/calc/financial_model.xlsx"), + "--fixture", + help="Cache-free formula fixture workbook.", + ), + expected: Path = typer.Option( + Path("fixtures/calc/expected_values.json"), + "--expected", + help="Oracle expected-values JSON for the fixture.", + ), + output_dir: Path = typer.Option( + Path("results/calc"), + "--output", + "-o", + help="Directory to save calculation-tier results.", + ), +) -> None: + """Run the formula-recalculation tier against the oracle fixture. + + The fixture ships formulas without cached values, so every scored value + must be produced by the engine itself. + """ + from excelbench.harness.calc import run_calc_suite + + if not fixture.exists(): + console.print(f"[red]Error: fixture not found at {fixture}[/red]") + raise typer.Exit(1) + if not expected.exists(): + console.print(f"[red]Error: expected values not found at {expected}[/red]") + raise typer.Exit(1) + + console.print("[bold]Running formula-recalculation tier...[/bold]") + console.print(f" Fixture: {fixture}") + console.print(f" Oracle: {expected}") + console.print(f" Output: {output_dir}") + console.print() + + try: + results = run_calc_suite(fixture, expected, output_dir) + for name, engine in results["engines"].items(): + console.print( + f" {name}: {engine['status']}, {engine['matched']}/{engine['total']}" + ) + console.print() + console.print(f"[green]✓ Calculation results written to {output_dir}[/green]") + except Exception as e: + console.print(f"[red]Error: {e}[/red]") + raise typer.Exit(1) + + def show_summary(results: "BenchmarkResults") -> None: """Show a quick summary table of results.""" from excelbench.results.renderer import score_emoji diff --git a/src/excelbench/harness/adapters/__init__.py b/src/excelbench/harness/adapters/__init__.py index 196364c..eb09176 100644 --- a/src/excelbench/harness/adapters/__init__.py +++ b/src/excelbench/harness/adapters/__init__.py @@ -2,7 +2,11 @@ from typing import TypeAlias -from excelbench.harness.adapters.base import ExcelAdapter, ReadOnlyAdapter, WriteOnlyAdapter +from excelbench.harness.adapters.base import ( + ExcelAdapter, + ReadOnlyAdapter, + WriteOnlyAdapter, +) from excelbench.harness.adapters.openpyxl_adapter import OpenpyxlAdapter AdapterClass: TypeAlias = type[ExcelAdapter] @@ -16,6 +20,7 @@ def _is_available_adapter(adapter: AdapterClass | None) -> bool: return True return bool(is_available()) + try: from excelbench.harness.adapters.xlsxwriter_adapter import ( XlsxwriterAdapter as _XlsxwriterAdapter, @@ -25,7 +30,9 @@ def _is_available_adapter(adapter: AdapterClass | None) -> bool: else: XlsxwriterAdapter = _XlsxwriterAdapter try: - from excelbench.harness.adapters.calamine_adapter import CalamineAdapter as _CalamineAdapter + from excelbench.harness.adapters.calamine_adapter import ( + CalamineAdapter as _CalamineAdapter, + ) except ImportError: CalamineAdapter: AdapterClass | None = None else: @@ -75,14 +82,18 @@ def _is_available_adapter(adapter: AdapterClass | None) -> bool: WolfxlAdapter = _WolfxlAdapter try: - from excelbench.harness.adapters.pyumya_adapter import PyumyaAdapter as _PyumyaAdapter + from excelbench.harness.adapters.pyumya_adapter import ( + PyumyaAdapter as _PyumyaAdapter, + ) except ImportError: PyumyaAdapter: AdapterClass | None = None else: PyumyaAdapter = _PyumyaAdapter try: - from excelbench.harness.adapters.pylightxl_adapter import PylightxlAdapter as _PylightxlAdapter + from excelbench.harness.adapters.pylightxl_adapter import ( + PylightxlAdapter as _PylightxlAdapter, + ) except ImportError: PylightxlAdapter: AdapterClass | None = None else: @@ -94,7 +105,9 @@ def _is_available_adapter(adapter: AdapterClass | None) -> bool: else: XlrdAdapter = _XlrdAdapter try: - from excelbench.harness.adapters.pyexcel_adapter import PyexcelAdapter as _PyexcelAdapter + from excelbench.harness.adapters.pyexcel_adapter import ( + PyexcelAdapter as _PyexcelAdapter, + ) except ImportError: PyexcelAdapter: AdapterClass | None = None else: @@ -106,7 +119,9 @@ def _is_available_adapter(adapter: AdapterClass | None) -> bool: else: XlwtAdapter = _XlwtAdapter try: - from excelbench.harness.adapters.pandas_adapter import PandasAdapter as _PandasAdapter + from excelbench.harness.adapters.pandas_adapter import ( + PandasAdapter as _PandasAdapter, + ) except ImportError: PandasAdapter: AdapterClass | None = None else: @@ -129,13 +144,17 @@ def _is_available_adapter(adapter: AdapterClass | None) -> bool: else: OpenpyxlReadonlyAdapter = _OpenpyxlReadonlyAdapter try: - from excelbench.harness.adapters.polars_adapter import PolarsAdapter as _PolarsAdapter + from excelbench.harness.adapters.polars_adapter import ( + PolarsAdapter as _PolarsAdapter, + ) except ImportError: PolarsAdapter: AdapterClass | None = None else: PolarsAdapter = _PolarsAdapter try: - from excelbench.harness.adapters.tablib_adapter import TablibAdapter as _TablibAdapter + from excelbench.harness.adapters.tablib_adapter import ( + TablibAdapter as _TablibAdapter, + ) except ImportError: TablibAdapter: AdapterClass | None = None else: @@ -151,18 +170,39 @@ def _is_available_adapter(adapter: AdapterClass | None) -> bool: ExcelOracleAdapter = _ExcelOracleAdapter try: - from excelbench.harness.adapters.apache_poi_adapter import ApachePoiAdapter as _ApachePoiAdapter + from excelbench.harness.adapters.apache_poi_adapter import ( + ApachePoiAdapter as _ApachePoiAdapter, + ) except ImportError: ApachePoiAdapter: AdapterClass | None = None else: ApachePoiAdapter = _ApachePoiAdapter try: - from excelbench.harness.adapters.excelize_adapter import ExcelizeAdapter as _ExcelizeAdapter + from excelbench.harness.adapters.excelize_adapter import ( + ExcelizeAdapter as _ExcelizeAdapter, + ) except ImportError: ExcelizeAdapter: AdapterClass | None = None else: ExcelizeAdapter = _ExcelizeAdapter +try: + from excelbench.harness.adapters.aspose_cells_foss_adapter import ( + AsposeCellsFossAdapter as _AsposeCellsFossAdapter, + ) +except ImportError: + AsposeCellsFossAdapter: AdapterClass | None = None +else: + AsposeCellsFossAdapter = _AsposeCellsFossAdapter +try: + from excelbench.harness.adapters.zavora_adapter import ( + ZavoraAdapter as _ZavoraAdapter, + ) +except ImportError: + ZavoraAdapter: AdapterClass | None = None +else: + ZavoraAdapter = _ZavoraAdapter + __all__ = [ "ExcelAdapter", @@ -202,6 +242,8 @@ def _is_available_adapter(adapter: AdapterClass | None) -> bool: __all__.append("XlsxwriterConstmemAdapter") if OpenpyxlReadonlyAdapter is not None: __all__.append("OpenpyxlReadonlyAdapter") +if AsposeCellsFossAdapter is not None: + __all__.append("AsposeCellsFossAdapter") if PolarsAdapter is not None: __all__.append("PolarsAdapter") if TablibAdapter is not None: @@ -210,6 +252,8 @@ def _is_available_adapter(adapter: AdapterClass | None) -> bool: __all__.append("ApachePoiAdapter") if ExcelizeAdapter is not None: __all__.append("ExcelizeAdapter") +if ZavoraAdapter is not None: + __all__.append("ZavoraAdapter") def get_all_adapters() -> list[ExcelAdapter]: @@ -219,6 +263,8 @@ def get_all_adapters() -> list[ExcelAdapter]: adapters.append(XlsxwriterAdapter()) if CalamineAdapter is not None: adapters.append(CalamineAdapter()) + if AsposeCellsFossAdapter is not None: + adapters.append(AsposeCellsFossAdapter()) if RustCalamineAdapter is not None: adapters.append(RustCalamineAdapter()) # RustCalamineStyledAdapter is an internal WolfXL backend, not a standalone @@ -253,4 +299,6 @@ def get_all_adapters() -> list[ExcelAdapter]: adapters.append(ApachePoiAdapter()) if ExcelizeAdapter is not None and _is_available_adapter(ExcelizeAdapter): adapters.append(ExcelizeAdapter()) + if ZavoraAdapter is not None and _is_available_adapter(ZavoraAdapter): + adapters.append(ZavoraAdapter()) return adapters diff --git a/src/excelbench/harness/adapters/aspose_cells_foss_adapter.py b/src/excelbench/harness/adapters/aspose_cells_foss_adapter.py new file mode 100644 index 0000000..b090e26 --- /dev/null +++ b/src/excelbench/harness/adapters/aspose_cells_foss_adapter.py @@ -0,0 +1,866 @@ +"""Adapter for the :mod:`aspose.cells_foss` library.""" + +from __future__ import annotations + +from datetime import date, datetime +from pathlib import Path +from typing import Any + +try: + import aspose.cells_foss as aspose + from aspose.cells_foss.data_validation import ( + DataValidationOperator, + DataValidationType, + ) + from aspose.cells_foss.workbook_properties import DefinedName +except ImportError as exc: # pragma: no cover - exercised by the adapter registry. + raise ImportError( + "AsposeCellsFossAdapter requires the optional 'aspose-cells-foss' package." + ) from exc + +from excelbench.harness.adapters.base import ExcelAdapter +from excelbench.models import ( + BorderEdge, + BorderInfo, + BorderStyle, + CellFormat, + CellType, + CellValue, + LibraryInfo, +) + +JSONDict = dict[str, Any] + +_ERROR_FORMULA_MAP = { + "=1/0": "#DIV/0!", + "=NA()": "#N/A", + '="text"+1': "#VALUE!", + "=#REF!": "#REF!", + "=_undefined_name_": "#NAME?", + "=SQRT(-1)": "#NUM!", + "=A1:A2 B1:B2": "#NULL!", +} +_ERROR_VALUE_FORMULA_MAP = {value: key for key, value in _ERROR_FORMULA_MAP.items()} + + +_VALIDATION_TYPES = { + "none": DataValidationType.NONE, + "whole": DataValidationType.WHOLE_NUMBER, + "wholeNumber": DataValidationType.WHOLE_NUMBER, + "decimal": DataValidationType.DECIMAL, + "list": DataValidationType.LIST, + "date": DataValidationType.DATE, + "time": DataValidationType.TIME, + "textLength": DataValidationType.TEXT_LENGTH, + "text_length": DataValidationType.TEXT_LENGTH, + "custom": DataValidationType.CUSTOM, +} +_VALIDATION_TYPE_NAMES = { + DataValidationType.NONE: "none", + DataValidationType.WHOLE_NUMBER: "whole", + DataValidationType.DECIMAL: "decimal", + DataValidationType.LIST: "list", + DataValidationType.DATE: "date", + DataValidationType.TIME: "time", + DataValidationType.TEXT_LENGTH: "textLength", + DataValidationType.CUSTOM: "custom", +} +_VALIDATION_OPERATORS = { + "between": DataValidationOperator.BETWEEN, + "notBetween": DataValidationOperator.NOT_BETWEEN, + "equal": DataValidationOperator.EQUAL, + "notEqual": DataValidationOperator.NOT_EQUAL, + "greaterThan": DataValidationOperator.GREATER_THAN, + "lessThan": DataValidationOperator.LESS_THAN, + "greaterThanOrEqual": DataValidationOperator.GREATER_THAN_OR_EQUAL, + "lessThanOrEqual": DataValidationOperator.LESS_THAN_OR_EQUAL, +} +_VALIDATION_OPERATOR_NAMES = { + value: key for key, value in _VALIDATION_OPERATORS.items() +} + + +def _color_to_hex(value: Any) -> str | None: + """Normalize the library's RGB/ARGB colors to the benchmark's #RRGGBB form.""" + if not isinstance(value, str): + return None + raw = value.lstrip("#").upper() + if len(raw) == 8: + raw = raw[2:] + if len(raw) != 6 or any(char not in "0123456789ABCDEF" for char in raw): + return None + return f"#{raw}" + + +def _color_to_argb(value: str) -> str: + """Convert a benchmark #RRGGBB color to the library's AARRGGBB form.""" + raw = value.lstrip("#").upper() + if len(raw) == 6: + return f"FF{raw}" + if len(raw) == 8: + return raw + raise ValueError(f"Expected a six- or eight-digit hex color, got {value!r}") + + +def _cell_value_from_aspose_cell(cell: Any) -> CellValue: + """Convert an aspose-cells-foss cell to the benchmark's typed value model.""" + formula = getattr(cell, "formula", None) + value = getattr(cell, "value", None) + if isinstance(formula, str) and formula: + formula_text = formula if formula.startswith("=") else f"={formula}" + if formula_text in _ERROR_FORMULA_MAP: + return CellValue( + type=CellType.ERROR, value=_ERROR_FORMULA_MAP[formula_text] + ) + return CellValue(type=CellType.FORMULA, value=value, formula=formula_text) + if value is None: + return CellValue(type=CellType.BLANK) + if isinstance(value, bool): + return CellValue(type=CellType.BOOLEAN, value=value) + if isinstance(value, (int, float)): + return CellValue(type=CellType.NUMBER, value=value) + if isinstance(value, datetime): + if ( + value.hour == 0 + and value.minute == 0 + and value.second == 0 + and value.microsecond == 0 + ): + return CellValue(type=CellType.DATE, value=value.date()) + return CellValue(type=CellType.DATETIME, value=value) + if isinstance(value, date): + return CellValue(type=CellType.DATE, value=value) + if isinstance(value, str): + if value.startswith("#") and value.endswith("!") or value == "#N/A": + return CellValue(type=CellType.ERROR, value=value) + return CellValue(type=CellType.STRING, value=value) + return CellValue(type=CellType.STRING, value=str(value)) + + +def _edge_from_aspose_border(border: Any) -> BorderEdge | None: + """Convert one aspose-cells-foss border side to a benchmark border edge.""" + line_style = getattr(border, "line_style", "none") + if not isinstance(line_style, str) or line_style == "none": + return None + try: + style = BorderStyle(line_style) + except ValueError: + style = BorderStyle.THIN + return BorderEdge( + style=style, color=_color_to_hex(getattr(border, "color", None)) or "#000000" + ) + + +def _set_aspose_border_edge(target: Any, edge: BorderEdge | None) -> None: + """Apply a benchmark border edge to an aspose-cells-foss border side.""" + if edge is None: + target.line_style = "none" + return + target.line_style = edge.style.value + target.color = _color_to_argb(edge.color) + + +def _coordinates(cell_range: str) -> tuple[int, int, int, int]: + """Return zero-based top-left and bottom-right coordinates for an A1 range.""" + normalized = cell_range.replace("$", "").upper() + start, separator, end = normalized.partition(":") + if not separator: + end = start + start_row, start_col = aspose.Cells.coordinate_from_string(start) + end_row, end_col = aspose.Cells.coordinate_from_string(end) + return start_row - 1, start_col - 1, end_row - 1, end_col - 1 + + +def _center_section(value: Any) -> str | None: + """Extract the center section from an OOXML header/footer string.""" + if not isinstance(value, str) or "&C" not in value: + return None + center = value.split("&C", 1)[1] + for marker in ("&L", "&R"): + center = center.split(marker, 1)[0] + return center or None + + +class AsposeCellsFossAdapter(ExcelAdapter): + """Read/write Excel adapter for aspose-cells-foss 26.7.0 and compatible releases.""" + + @property + def info(self) -> LibraryInfo: + return LibraryInfo( + name="aspose-cells-foss", + version=str(getattr(aspose, "__version__", "unknown")), + language="python", + capabilities={"read", "write"}, + ) + + def open_workbook(self, path: Path) -> Any: + """Open an XLSX workbook for reading and modification.""" + return aspose.Workbook(str(path)) + + def close_workbook(self, workbook: Any) -> None: + """Release a workbook; aspose-cells-foss keeps no open file handle.""" + del workbook + + def get_sheet_names(self, workbook: Any) -> list[str]: + """Return worksheet names in workbook order.""" + return [str(worksheet.name) for worksheet in workbook.worksheets] + + def read_sheet_values( + self, workbook: Any, sheet: str, cell_range: str | None = None + ) -> list[list[CellValue]]: + """Read a rectangular cell range as typed benchmark values.""" + worksheet = workbook.get_worksheet(sheet) + if worksheet is None: + raise ValueError(f"Worksheet {sheet!r} not found") + if cell_range is None: + cells = worksheet.cells + if not cells._cells: + return [] + rows_and_columns = [ + aspose.Cells.coordinate_from_string(ref) for ref in cells._cells + ] + min_row = min(row for row, _ in rows_and_columns) + max_row = max(row for row, _ in rows_and_columns) + min_col = min(column for _, column in rows_and_columns) + max_col = max(column for _, column in rows_and_columns) + else: + start_row, start_col, end_row, end_col = _coordinates(cell_range) + min_row, max_row = start_row + 1, end_row + 1 + min_col, max_col = start_col + 1, end_col + 1 + return [ + [_cell_value_from_aspose_cell(cell) for cell in row] + for row in worksheet.cells.iter_rows( + min_row=min_row, max_row=max_row, min_col=min_col, max_col=max_col + ) + ] + + def read_cell_value(self, workbook: Any, sheet: str, cell: str) -> CellValue: + """Read a typed value, preserving formula text.""" + return _cell_value_from_aspose_cell(workbook.get_worksheet(sheet).cells[cell]) + + def read_cell_format(self, workbook: Any, sheet: str, cell: str) -> CellFormat: + """Read a cell's font, fill, number-format, and alignment properties.""" + style = workbook.get_worksheet(sheet).cells[cell].style + font = style.font + fill = style.fill + alignment = style.alignment + return CellFormat( + bold=True if font.bold else None, + italic=True if font.italic else None, + underline="single" if font.underline else None, + strikethrough=True if font.strikethrough else None, + font_name=str(font.name) if font.name else None, + font_size=float(font.size) if font.size else None, + font_color=_color_to_hex(font.color), + bg_color=_color_to_hex(fill.foreground_color) + if fill.pattern_type == "solid" + else None, + number_format=str(style.number_format) if style.number_format else None, + h_align=alignment.horizontal if alignment.horizontal != "general" else None, + v_align=alignment.vertical if alignment.vertical != "bottom" else None, + wrap=True if alignment.wrap_text else None, + rotation=alignment.text_rotation if alignment.text_rotation else None, + indent=alignment.indent if alignment.indent else None, + ) + + def read_cell_border(self, workbook: Any, sheet: str, cell: str) -> BorderInfo: + """Read all four and diagonal borders from a cell.""" + borders = workbook.get_worksheet(sheet).cells[cell].style.borders + return BorderInfo( + top=_edge_from_aspose_border(borders.top), + bottom=_edge_from_aspose_border(borders.bottom), + left=_edge_from_aspose_border(borders.left), + right=_edge_from_aspose_border(borders.right), + diagonal_up=_edge_from_aspose_border(borders.diagonal) + if borders.diagonal_up + else None, + diagonal_down=_edge_from_aspose_border(borders.diagonal) + if borders.diagonal_down + else None, + ) + + def read_row_height(self, workbook: Any, sheet: str, row: int) -> float | None: + """Read a 1-indexed row's height in points.""" + value = workbook.get_worksheet(sheet).cells.get_row_height(row - 1) + return float(value) if isinstance(value, (int, float)) else None + + def read_column_width(self, workbook: Any, sheet: str, column: str) -> float | None: + """Read a column's display width in characters.""" + value = workbook.get_worksheet(sheet).cells.get_column_width(column) + return float(value) if isinstance(value, (int, float)) else None + + def read_merged_ranges(self, workbook: Any, sheet: str) -> list[str]: + """Read merged A1 ranges.""" + return workbook.get_worksheet(sheet).cells.get_merged_cells() + + def read_conditional_formats(self, workbook: Any, sheet: str) -> list[JSONDict]: + """Read conditional-format rules exposed by the FOSS API.""" + rules: list[JSONDict] = [] + for conditional_format in workbook.get_worksheet(sheet).conditional_formats: + rule_type = conditional_format.type + if rule_type == "cellValue": + rule_type = "cellIs" + elif rule_type == "formula": + rule_type = "expression" + rules.append( + { + "range": conditional_format.range, + "rule_type": rule_type, + "operator": conditional_format.operator, + "formula": conditional_format.formula + if conditional_format.formula is not None + else conditional_format.formula1, + "priority": conditional_format.priority, + "stop_if_true": conditional_format.stop_if_true, + "format": { + **( + { + "bg_color": _color_to_hex( + conditional_format.fill.foreground_color + ) + } + if conditional_format.fill.pattern_type == "solid" + and _color_to_hex(conditional_format.fill.foreground_color) + else {} + ), + **( + {"font_color": _color_to_hex(conditional_format.font.color)} + if _color_to_hex(conditional_format.font.color) + not in (None, "#000000") + else {} + ), + }, + } + ) + return rules + + def read_data_validations(self, workbook: Any, sheet: str) -> list[JSONDict]: + """Read data-validation rules.""" + validations: list[JSONDict] = [] + for validation in workbook.get_worksheet(sheet).data_validations: + validation_type = _VALIDATION_TYPE_NAMES.get( + validation.type, str(validation.type) + ) + operator = _VALIDATION_OPERATOR_NAMES.get( + validation.operator, str(validation.operator) + ) + validations.append( + { + "range": validation.sqref, + "validation_type": validation_type, + "operator": operator, + "formula1": validation.formula1, + "formula2": validation.formula2, + "allow_blank": validation.allow_blank, + "show_input": validation.show_input_message, + "show_error": validation.show_error_message, + "prompt_title": validation.input_title, + "prompt": validation.input_message, + "error_title": validation.error_title, + "error": validation.error_message, + } + ) + return validations + + def read_hyperlinks(self, workbook: Any, sheet: str) -> list[JSONDict]: + """Read worksheet hyperlinks with internal/external targets normalized.""" + worksheet = workbook.get_worksheet(sheet) + return [ + { + "cell": link.range, + "target": link.sub_address if link.sub_address else link.address, + "display": link.text_to_display or worksheet.cells[link.range].value, + "tooltip": link.screen_tip or None, + "internal": bool(link.sub_address), + } + for link in worksheet.hyperlinks + ] + + def read_images(self, workbook: Any, sheet: str) -> list[JSONDict]: + """Reject image reads because one-cell drawing anchors are not surfaced reliably.""" + self.unsupported_operation( + "read_images", + "aspose-cells-foss does not preserve the source one-cell versus two-cell anchor kind.", + ) + + def read_pivot_tables(self, workbook: Any, sheet: str) -> list[JSONDict]: + """Reject pivot reads because the FOSS API has no pivot-table model.""" + self.unsupported_operation( + "read_pivot_tables", "aspose-cells-foss exposes no pivot-table API." + ) + + def read_comments(self, workbook: Any, sheet: str) -> list[JSONDict]: + """Read legacy cell comments.""" + worksheet = workbook.get_worksheet(sheet) + return [ + { + "cell": cell_ref, + "text": comment["text"], + "author": comment["author"], + "threaded": False, + } + for cell_ref, cell in worksheet.cells._cells.items() + if (comment := cell.comment) is not None + ] + + def read_freeze_panes(self, workbook: Any, sheet: str) -> JSONDict: + """Read frozen or split pane settings.""" + pane = workbook.get_worksheet(sheet).properties.pane + if pane.state is None: + return {} + result: JSONDict = { + "mode": "freeze" if pane.state in {"frozen", "frozenSplit"} else "split" + } + if pane.x_split is not None: + result["x_split"] = int(pane.x_split) + if pane.y_split is not None: + result["y_split"] = int(pane.y_split) + if pane.top_left_cell is not None: + result["top_left_cell"] = pane.top_left_cell + if pane.active_pane is not None: + result["active_pane"] = pane.active_pane + return result + + def read_named_ranges(self, workbook: Any, sheet: str) -> list[JSONDict]: + """Read workbook names plus names local to the requested worksheet.""" + sheet_index = self.get_sheet_names(workbook).index(sheet) + return [ + { + "name": defined_name.name, + "scope": "sheet" + if defined_name.local_sheet_id is not None + else "workbook", + "refers_to": str(defined_name.refers_to).lstrip("="), + } + for defined_name in workbook.properties.defined_names + if defined_name.local_sheet_id is None + or defined_name.local_sheet_id == sheet_index + ] + + def read_tables(self, workbook: Any, sheet: str) -> list[JSONDict]: + """Read structured table definitions.""" + return [ + { + "name": table.display_name or table.name, + "ref": table.ref, + "header_row": table.has_headers, + "totals_row": table.show_totals_row, + "style": table.table_style_info.name + if table.table_style_info + else None, + "columns": [column.name for column in table.columns], + "autofilter": table.show_auto_filter, + } + for table in workbook.get_worksheet(sheet).tables + ] + + def read_sheet_protection(self, workbook: Any, sheet: str) -> JSONDict: + """Read raw OOXML-equivalent sheet-protection flags.""" + protection = workbook.get_worksheet(sheet).properties.protection + return { + "protected": bool(protection.sheet), + "password_hash_present": bool( + protection.password + or protection.hash_value + or protection.algorithm_name + ), + "format_cells": protection.format_cells, + "insert_rows": protection.insert_rows, + "select_locked_cells": protection.select_locked_cells, + "select_unlocked_cells": protection.select_unlocked_cells, + "sort": protection.sort, + "auto_filter": protection.auto_filter, + } + + def read_page_setup(self, workbook: Any, sheet: str) -> JSONDict: + """Read print settings supported by the FOSS worksheet-properties API.""" + worksheet = workbook.get_worksheet(sheet) + page_setup = worksheet.properties.page_setup + header_footer = worksheet.properties.header_footer + return { + "orientation": page_setup.orientation, + "fit_to_width": page_setup.fit_to_width, + "fit_to_height": page_setup.fit_to_height, + "scale": page_setup.scale, + "print_title_rows": None, + "header_center": _center_section(header_footer.odd_header), + "footer_center": _center_section(header_footer.odd_footer), + } + + def read_chart_anchors(self, workbook: Any, sheet: str) -> list[JSONDict]: + """Read charts and their explicit two-cell drawing anchors.""" + results: list[JSONDict] = [] + for chart in workbook.get_worksheet(sheet).charts: + chart_type = getattr(chart.type, "name", str(chart.type)).lower() + results.append( + { + "type": chart_type, + "anchor_type": "twoCell", + "from": aspose.Cells.coordinate_to_string( + chart._upper_left_row + 1, chart._upper_left_column + 1 + ), + "to": aspose.Cells.coordinate_to_string( + chart._lower_right_row + 1, chart._lower_right_column + 1 + ), + } + ) + return results + + def create_workbook(self) -> Any: + """Create an empty workbook without an implicit worksheet.""" + workbook = aspose.Workbook() + workbook.remove_worksheet(0) + return workbook + + def add_sheet(self, workbook: Any, name: str) -> None: + """Add a named worksheet.""" + workbook.add_worksheet(name) + + def write_sheet_values( + self, workbook: Any, sheet: str, start_cell: str, values: list[list[Any]] + ) -> None: + """Write a rectangular grid of raw values for throughput workloads.""" + start_row, start_col = aspose.Cells.coordinate_from_string(start_cell) + cells = workbook.get_worksheet(sheet).cells + for row_offset, values_row in enumerate(values): + for column_offset, raw_value in enumerate(values_row): + if raw_value is not None: + cells.cell( + start_row + row_offset, start_col + column_offset + ).value = raw_value + + def write_cell_value( + self, workbook: Any, sheet: str, cell: str, value: CellValue + ) -> None: + """Write a typed cell value, including formulas and formula-produced errors.""" + target = workbook.get_worksheet(sheet).cells[cell] + target.formula = None + if value.type == CellType.BLANK: + target.value = None + elif value.type == CellType.FORMULA: + formula = value.formula if value.formula is not None else value.value + if not isinstance(formula, str): + raise ValueError("Formula CellValue must provide a formula string") + target.formula = formula if formula.startswith("=") else f"={formula}" + target.value = None + elif value.type == CellType.ERROR: + formula = _ERROR_VALUE_FORMULA_MAP.get(str(value.value)) + if formula is None: + self.unsupported_operation( + "write_cell_value", + f"Cannot serialize Excel error {value.value!r} without a formula.", + ) + target.formula = formula + target.value = None + else: + target.value = value.value + + def write_cell_format( + self, workbook: Any, sheet: str, cell: str, format: CellFormat + ) -> None: + """Apply benchmark formatting fields the FOSS style model can represent.""" + style = workbook.get_worksheet(sheet).cells[cell].style + if format.bold is not None: + style.font.bold = format.bold + if format.italic is not None: + style.font.italic = format.italic + if format.underline is not None: + if format.underline not in {"single", True}: + self.unsupported_operation( + "write_cell_format", + ( + "aspose-cells-foss supports only a single underline, " + "not accounting or double variants." + ), + ) + style.font.underline = True + if format.strikethrough is not None: + style.font.strikethrough = format.strikethrough + if format.font_name is not None: + style.font.name = format.font_name + if format.font_size is not None: + style.font.size = format.font_size + if format.font_color is not None: + style.font.color = _color_to_argb(format.font_color) + if format.bg_color is not None: + style.fill.set_solid_fill(_color_to_argb(format.bg_color)) + if format.number_format is not None: + style.number_format = format.number_format + if format.h_align is not None: + style.alignment.horizontal = format.h_align + if format.v_align is not None: + style.alignment.vertical = format.v_align + if format.wrap is not None: + style.alignment.wrap_text = format.wrap + if format.rotation is not None: + style.alignment.text_rotation = format.rotation + if format.indent is not None: + style.alignment.indent = format.indent + + def write_cell_border( + self, workbook: Any, sheet: str, cell: str, border: BorderInfo + ) -> None: + """Apply four-side and diagonal borders.""" + borders = workbook.get_worksheet(sheet).cells[cell].style.borders + _set_aspose_border_edge(borders.top, border.top) + _set_aspose_border_edge(borders.bottom, border.bottom) + _set_aspose_border_edge(borders.left, border.left) + _set_aspose_border_edge(borders.right, border.right) + diagonal = border.diagonal_up or border.diagonal_down + _set_aspose_border_edge(borders.diagonal, diagonal) + borders.diagonal_up = border.diagonal_up is not None + borders.diagonal_down = border.diagonal_down is not None + + def set_row_height( + self, workbook: Any, sheet: str, row: int, height: float + ) -> None: + """Set a 1-indexed row height in points.""" + workbook.get_worksheet(sheet).cells.set_row_height(row - 1, height) + + def set_column_width( + self, workbook: Any, sheet: str, column: str, width: float + ) -> None: + """Set a column width in display characters.""" + workbook.get_worksheet(sheet).cells.set_column_width(column, width) + + def merge_cells(self, workbook: Any, sheet: str, cell_range: str) -> None: + """Merge an A1 range.""" + workbook.get_worksheet(sheet).cells.merge_range(cell_range) + + def add_conditional_format(self, workbook: Any, sheet: str, rule: JSONDict) -> None: + """Add a conditional-format rule.""" + config = rule.get("cf_rule", rule) + rule_type = str(config.get("rule_type") or "") + type_mapping = { + "cellIs": "cellValue", + "cellIsRule": "cellValue", + "expression": "formula", + } + aspose_type = type_mapping.get(rule_type, rule_type) + if not aspose_type: + raise ValueError("Conditional-format rule requires rule_type") + conditional_format = workbook.get_worksheet(sheet).conditional_formats.add() + conditional_format.type = aspose_type + conditional_format.range = config.get("range") + if config.get("operator") is not None: + conditional_format.operator = config["operator"] + formula = config.get("formula") + if aspose_type == "formula": + conditional_format.formula = formula + elif formula is not None: + conditional_format.formula1 = formula + if config.get("priority") is not None: + conditional_format.priority = int(config["priority"]) + if config.get("stop_if_true") is not None: + conditional_format.stop_if_true = bool(config["stop_if_true"]) + style = config.get("format") or {} + if style.get("bg_color"): + conditional_format.fill.set_solid_fill( + _color_to_argb(str(style["bg_color"])) + ) + if style.get("font_color"): + conditional_format.font.color = _color_to_argb(str(style["font_color"])) + + def add_data_validation( + self, workbook: Any, sheet: str, validation: JSONDict + ) -> None: + """Add an Excel data-validation rule.""" + config = validation.get("validation", validation) + raw_type = str(config.get("validation_type") or "none") + validation_type = _VALIDATION_TYPES.get(raw_type) + if validation_type is None: + self.unsupported_operation( + "add_data_validation", f"Unsupported data-validation type {raw_type!r}." + ) + raw_operator = str(config.get("operator") or "between") + operator = _VALIDATION_OPERATORS.get(raw_operator) + if operator is None: + self.unsupported_operation( + "add_data_validation", + f"Unsupported data-validation operator {raw_operator!r}.", + ) + target = workbook.get_worksheet(sheet).data_validations.add( + str(config.get("range") or ""), + validation_type, + operator, + config.get("formula1"), + config.get("formula2"), + ) + if config.get("allow_blank") is not None: + target.allow_blank = bool(config["allow_blank"]) + if config.get("show_input") is not None: + target.show_input_message = bool(config["show_input"]) + if config.get("show_error") is not None: + target.show_error_message = bool(config["show_error"]) + if config.get("prompt_title") is not None: + target.input_title = str(config["prompt_title"]) + if config.get("prompt") is not None: + target.input_message = str(config["prompt"]) + if config.get("error_title") is not None: + target.error_title = str(config["error_title"]) + if config.get("error") is not None: + target.error_message = str(config["error"]) + + def add_hyperlink(self, workbook: Any, sheet: str, link: JSONDict) -> None: + """Add an internal or external hyperlink.""" + config = link.get("hyperlink", link) + cell = str(config.get("cell") or "") + target = str(config.get("target") or "") + internal = bool(config.get("internal")) + if not cell or not target: + raise ValueError("Hyperlinks require both cell and target") + hyperlink = workbook.get_worksheet(sheet).hyperlinks.add( + cell, + "" if internal else target, + target.lstrip("#") if internal else "", + str(config.get("display") or ""), + str(config.get("tooltip") or ""), + ) + if config.get("display") is not None: + workbook.get_worksheet(sheet).cells[cell].value = config["display"] + del hyperlink + + def add_image(self, workbook: Any, sheet: str, image: JSONDict) -> None: + """Reject image writes because the adapter cannot create one-cell anchors.""" + self.unsupported_operation( + "add_image", + ( + "aspose-cells-foss writes only two-cell picture anchors, " + "while the benchmark requires one-cell anchors." + ), + ) + + def add_pivot_table(self, workbook: Any, sheet: str, pivot: JSONDict) -> None: + """Reject pivot writes because the FOSS API has no pivot-table model.""" + self.unsupported_operation( + "add_pivot_table", "aspose-cells-foss exposes no pivot-table API." + ) + + def add_comment(self, workbook: Any, sheet: str, comment: JSONDict) -> None: + """Add a legacy note/comment to a cell.""" + config = comment.get("comment", comment) + cell = config.get("cell") + text = config.get("text") + if cell is None or text is None: + raise ValueError("Comments require both cell and text") + workbook.get_worksheet(sheet).cells[str(cell)].set_comment( + str(text), str(config.get("author") or "") + ) + + def set_freeze_panes(self, workbook: Any, sheet: str, settings: JSONDict) -> None: + """Set frozen or split worksheet panes.""" + config = settings.get("freeze", settings) + mode = config.get("mode") + if mode not in {"freeze", "split"}: + self.unsupported_operation( + "set_freeze_panes", + f"Unsupported pane mode {mode!r}; expected 'freeze' or 'split'.", + ) + pane = workbook.get_worksheet(sheet).properties.pane + pane.state = "frozen" if mode == "freeze" else "split" + pane.x_split = config.get("x_split") + pane.y_split = config.get("y_split") + pane.top_left_cell = config.get("top_left_cell") + pane.active_pane = config.get("active_pane") + + def add_named_range(self, workbook: Any, sheet: str, named_range: JSONDict) -> None: + """Add a workbook- or sheet-scoped named range.""" + config = named_range.get("named_range", named_range) + name = config.get("name") + refers_to = config.get("refers_to") + if not name or not refers_to: + raise ValueError("Named ranges require name and refers_to") + scope = config.get("scope") or "workbook" + local_sheet_id = ( + self.get_sheet_names(workbook).index(sheet) if scope == "sheet" else None + ) + workbook.properties.defined_names.add( + DefinedName(str(name), str(refers_to).lstrip("="), local_sheet_id) + ) + + def add_table(self, workbook: Any, sheet: str, table: JSONDict) -> None: + """Add a structured table and apply its supported metadata.""" + config = table.get("table", table) + name = config.get("name") + cell_range = config.get("ref") or config.get("range") + if not name or not cell_range: + raise ValueError("Tables require both name and ref") + worksheet = workbook.get_worksheet(sheet) + created = worksheet.tables.add_with_range( + str(cell_range), str(name), bool(config.get("header_row", True)) + ) + created.show_totals_row = bool(config.get("totals_row", False)) + created.show_auto_filter = bool(config.get("autofilter", True)) + if config.get("style") is not None: + created.table_style_info.name = str(config["style"]) + columns = config.get("columns") + if isinstance(columns, list) and len(columns) == len(created.columns): + for column, name_value in zip(created.columns, columns, strict=True): + column.name = str(name_value) + + def set_sheet_protection( + self, workbook: Any, sheet: str, settings: JSONDict + ) -> None: + """Apply raw OOXML-equivalent sheet protection settings.""" + config = settings.get("protection", settings) + protection = workbook.get_worksheet(sheet).properties.protection + property_names = { + "protected": "sheet", + "format_cells": "format_cells", + "insert_rows": "insert_rows", + "select_locked_cells": "select_locked_cells", + "select_unlocked_cells": "select_unlocked_cells", + "sort": "sort", + "auto_filter": "auto_filter", + } + for input_name, property_name in property_names.items(): + if config.get(input_name) is not None: + setattr(protection, property_name, bool(config[input_name])) + if config.get("password") is not None: + protection.password = str(config["password"]) + + def set_page_setup(self, workbook: Any, sheet: str, settings: JSONDict) -> None: + """Apply supported page setup and centered header/footer text.""" + config = settings.get("page_setup", settings) + if config.get("print_title_rows") is not None: + self.unsupported_operation( + "set_page_setup", "aspose-cells-foss has no print-title-rows API." + ) + worksheet = workbook.get_worksheet(sheet) + page_setup = worksheet.properties.page_setup + for key in ("orientation", "fit_to_width", "fit_to_height", "scale"): + if config.get(key) is not None: + setattr(page_setup, key, config[key]) + if config.get("header_center") is not None: + worksheet.properties.header_footer.odd_header = ( + f"&C{config['header_center']}" + ) + if config.get("footer_center") is not None: + worksheet.properties.header_footer.odd_footer = ( + f"&C{config['footer_center']}" + ) + + def add_chart_with_anchor(self, workbook: Any, sheet: str, chart: JSONDict) -> None: + """Add a line or bar chart with a two-cell anchor and first data series.""" + config = chart.get("chart", chart) + chart_type_name = str(config.get("type") or "bar").upper() + chart_type = getattr(aspose.ChartType, chart_type_name, None) + if chart_type not in {aspose.ChartType.BAR, aspose.ChartType.LINE}: + self.unsupported_operation( + "add_chart_with_anchor", + f"Unsupported chart type {config.get('type')!r}.", + ) + data_ref = config.get("data_ref") + if not data_ref: + raise ValueError("add_chart_with_anchor requires data_ref") + from_row, from_column, to_row, to_column = _coordinates( + f"{config.get('from') or 'B2'}:{config.get('to') or 'H12'}" + ) + charts = workbook.get_worksheet(sheet).charts + chart_index = charts.add(chart_type, from_row, from_column, to_row, to_column) + series_chart = charts[chart_index] + series_chart.add_series(str(data_ref), config.get("categories_ref")) + + def save_workbook(self, workbook: Any, path: Path) -> None: + """Save a workbook as XLSX.""" + workbook.save(str(path)) diff --git a/src/excelbench/harness/adapters/base.py b/src/excelbench/harness/adapters/base.py index 1e2d0fa..9ec7889 100644 --- a/src/excelbench/harness/adapters/base.py +++ b/src/excelbench/harness/adapters/base.py @@ -18,6 +18,7 @@ JSONDict = dict[str, Any] + class UnsupportedAdapterOperationError(NotImplementedError): """Structured exception for adapter operations a library cannot support.""" @@ -31,7 +32,9 @@ def __init__(self, *, adapter: str, operation: str, reason: str) -> None: def _infer_diagnostic_category(exc: Exception) -> DiagnosticCategory: name = type(exc).__name__.lower() message = str(exc).lower() - if isinstance(exc, (FileNotFoundError, PermissionError, IsADirectoryError, OSError)): + if isinstance( + exc, (FileNotFoundError, PermissionError, IsADirectoryError, OSError) + ): if "format" in message or "zip" in message or "corrupt" in message: return DiagnosticCategory.PARSE return DiagnosticCategory.FILE_IO @@ -98,7 +101,6 @@ def unsupported_operation(self, operation: str, reason: str) -> None: adapter=self.name, operation=operation, reason=reason ) - def map_error_to_diagnostic( self, *, @@ -387,6 +389,81 @@ def add_table(self, workbook: Any, sheet: str, table: JSONDict) -> None: raise NotImplementedError(f"{self.name} does not implement table writes") + def read_sheet_protection(self, workbook: Any, sheet: str) -> JSONDict: + """Read sheet protection settings (raw OOXML attribute semantics). + + Returns a dict with keys (attribute True means the action is + BLOCKED while protection is active, matching sheetProtection XML): + - protected: bool (sheetProtection@sheet) + - password_hash_present: bool (any password hash stored) + - format_cells: bool | None + - insert_rows: bool | None + - select_locked_cells: bool | None + - select_unlocked_cells: bool | None + - sort: bool | None + - auto_filter: bool | None + """ + + raise NotImplementedError( + f"{self.name} does not implement sheet protection reads" + ) + + def set_sheet_protection( + self, workbook: Any, sheet: str, settings: JSONDict + ) -> None: + """Apply sheet protection settings. + + settings uses the same keys as read_sheet_protection (without + password_hash_present; use settings["password"] for a plain password + when the library hashes it internally). + """ + + raise NotImplementedError( + f"{self.name} does not implement sheet protection writes" + ) + + def read_page_setup(self, workbook: Any, sheet: str) -> JSONDict: + """Read page setup / print settings. + + Returns a dict with keys: + - orientation: "portrait" | "landscape" | None + - fit_to_width: int | None + - fit_to_height: int | None + - scale: int | None + - print_title_rows: str | None (e.g. "$1:$2") + - header_center: str | None + - footer_center: str | None + """ + + raise NotImplementedError(f"{self.name} does not implement page setup reads") + + def set_page_setup(self, workbook: Any, sheet: str, settings: JSONDict) -> None: + """Apply page setup / print settings (same keys as read_page_setup).""" + + raise NotImplementedError(f"{self.name} does not implement page setup writes") + + def read_chart_anchors(self, workbook: Any, sheet: str) -> list[JSONDict]: + """Read chart anchors from a sheet. + + Returns a list of dicts with keys: + - type: normalized chart type ("bar", "line", "pie", ...) + - anchor_type: "twoCell" | "oneCell" | "absolute" | None + - from: top-left cell ref (e.g. "B2") + - to: bottom-right cell ref (e.g. "H12"), None when not two-cell + """ + + raise NotImplementedError(f"{self.name} does not implement chart anchor reads") + + def add_chart_with_anchor(self, workbook: Any, sheet: str, chart: JSONDict) -> None: + """Add a chart with an explicit two-cell anchor. + + chart dict keys: type ("bar" | "line"), from, to (cell refs), + data_ref (range on the same sheet feeding the first series), + categories_ref (optional range for category labels). + """ + + raise NotImplementedError(f"{self.name} does not implement chart anchor writes") + # ========================================================================= # Write Operations # ========================================================================= @@ -501,7 +578,9 @@ def add_conditional_format(self, workbook: Any, sheet: str, rule: JSONDict) -> N ... @abstractmethod - def add_data_validation(self, workbook: Any, sheet: str, validation: JSONDict) -> None: + def add_data_validation( + self, workbook: Any, sheet: str, validation: JSONDict + ) -> None: """Add a data validation rule to a sheet.""" ... @@ -608,7 +687,9 @@ def merge_cells(self, workbook: Any, sheet: str, cell_range: str) -> None: def add_conditional_format(self, workbook: Any, sheet: str, rule: JSONDict) -> None: raise NotImplementedError(f"{self.name} is read-only") - def add_data_validation(self, workbook: Any, sheet: str, validation: JSONDict) -> None: + def add_data_validation( + self, workbook: Any, sheet: str, validation: JSONDict + ) -> None: raise NotImplementedError(f"{self.name} is read-only") def add_hyperlink(self, workbook: Any, sheet: str, link: JSONDict) -> None: diff --git a/src/excelbench/harness/adapters/openpyxl_adapter.py b/src/excelbench/harness/adapters/openpyxl_adapter.py index a22e256..e5870f7 100644 --- a/src/excelbench/harness/adapters/openpyxl_adapter.py +++ b/src/excelbench/harness/adapters/openpyxl_adapter.py @@ -107,7 +107,12 @@ def _cell_value_from_openpyxl_cell(c: Any) -> CellValue: return CellValue(type=CellType.DATE, value=value) if isinstance(value, datetime): - if value.hour == 0 and value.minute == 0 and value.second == 0 and value.microsecond == 0: + if ( + value.hour == 0 + and value.minute == 0 + and value.second == 0 + and value.microsecond == 0 + ): return CellValue(type=CellType.DATE, value=value.date()) return CellValue(type=CellType.DATETIME, value=value) @@ -127,7 +132,9 @@ def _cell_value_from_openpyxl_cell(c: Any) -> CellValue: if not formula_str.startswith("=") and value: formula_str = str(value) if formula_str in ERROR_FORMULA_MAP: - return CellValue(type=CellType.ERROR, value=ERROR_FORMULA_MAP[formula_str]) + return CellValue( + type=CellType.ERROR, value=ERROR_FORMULA_MAP[formula_str] + ) return CellValue(type=CellType.FORMULA, value=value, formula=formula_str) return CellValue(type=CellType.STRING, value=value) @@ -395,7 +402,9 @@ def read_merged_ranges(self, workbook: Workbook, sheet: str) -> list[str]: ws = workbook[sheet] return [str(rng) for rng in ws.merged_cells.ranges] - def read_conditional_formats(self, workbook: Workbook, sheet: str) -> list[JSONDict]: + def read_conditional_formats( + self, workbook: Workbook, sheet: str + ) -> list[JSONDict]: ws = workbook[sheet] rules: list[JSONDict] = [] cf_rules = getattr(ws.conditional_formatting, "_cf_rules", {}) @@ -407,7 +416,9 @@ def read_conditional_formats(self, workbook: Workbook, sheet: str) -> list[JSOND range_value = str(sqref) if range_value.startswith("", "").strip() + range_value.replace("", "") + .strip() ) for rule in rule_list: entry: dict[str, Any] = { @@ -422,11 +433,19 @@ def read_conditional_formats(self, workbook: Workbook, sheet: str) -> list[JSOND if getattr(rule, "formula", None): entry["formula"] = rule.formula[0] if rule.formula else None dxf = getattr(rule, "dxf", None) - if dxf and getattr(dxf, "fill", None) and getattr(dxf.fill, "fgColor", None): + if ( + dxf + and getattr(dxf, "fill", None) + and getattr(dxf.fill, "fgColor", None) + ): bg = _openpyxl_color_to_hex(dxf.fill.fgColor) if bg: entry["format"]["bg_color"] = bg - if dxf and getattr(dxf, "font", None) and getattr(dxf.font, "color", None): + if ( + dxf + and getattr(dxf, "font", None) + and getattr(dxf.font, "color", None) + ): fc = _openpyxl_color_to_hex(dxf.font.color) if fc: entry["format"]["font_color"] = fc @@ -534,11 +553,15 @@ def read_pivot_tables(self, workbook: Workbook, sheet: str) -> list[JSONDict]: for pivot in pivot_list: source_range = None cache = getattr(pivot, "cache", None) - cache_source = getattr(cache, "cacheSource", None) if cache is not None else None + cache_source = ( + getattr(cache, "cacheSource", None) if cache is not None else None + ) if cache_source is not None: worksheet_source = getattr(cache_source, "worksheetSource", None) ref = ( - getattr(worksheet_source, "ref", None) if worksheet_source is not None else None + getattr(worksheet_source, "ref", None) + if worksheet_source is not None + else None ) source_sheet = ( getattr(worksheet_source, "sheet", None) @@ -635,7 +658,11 @@ def _normalize_refers_to(value: Any) -> str: sheet_part, addr = raw.split("!", 1) # Strip only wrapper quotes used for sheet names with spaces. # Preserve embedded apostrophes by unescaping doubled quotes. - if sheet_part.startswith("'") and sheet_part.endswith("'") and len(sheet_part) >= 2: + if ( + sheet_part.startswith("'") + and sheet_part.endswith("'") + and len(sheet_part) >= 2 + ): sheet_part = sheet_part[1:-1].replace("''", "'") return f"{sheet_part}!{addr}" @@ -712,7 +739,11 @@ def read_tables(self, workbook: Workbook, sheet: str) -> list[JSONDict]: ref = getattr(tbl, "ref", None) if isinstance(ref, str) and ref: min_col, min_row, max_col, _ = range_boundaries(ref) - if min_col is not None and min_row is not None and max_col is not None: + if ( + min_col is not None + and min_row is not None + and max_col is not None + ): for c in range(int(min_col), int(max_col) + 1): v = ws.cell(row=int(min_row), column=c).value cols.append("" if v is None else str(v)) @@ -723,7 +754,8 @@ def read_tables(self, workbook: Workbook, sheet: str) -> list[JSONDict]: out.append( { - "name": getattr(tbl, "displayName", None) or getattr(tbl, "name", None), + "name": getattr(tbl, "displayName", None) + or getattr(tbl, "name", None), "ref": getattr(tbl, "ref", None), "header_row": getattr(tbl, "headerRowCount", 1) != 0, "totals_row": (getattr(tbl, "totalsRowCount", 0) or 0) > 0, @@ -968,7 +1000,9 @@ def merge_cells(self, workbook: Workbook, sheet: str, cell_range: str) -> None: ws = workbook[sheet] ws.merge_cells(cell_range) - def add_conditional_format(self, workbook: Workbook, sheet: str, rule: JSONDict) -> None: + def add_conditional_format( + self, workbook: Workbook, sheet: str, rule: JSONDict + ) -> None: ws = workbook[sheet] cf = rule.get("cf_rule", rule) range_ref = cf.get("range") @@ -983,7 +1017,9 @@ def add_conditional_format(self, workbook: Workbook, sheet: str, rule: JSONDict) if fmt.get("bg_color"): hex_color = fmt["bg_color"].lstrip("#") fill = PatternFill( - start_color=f"FF{hex_color}", end_color=f"FF{hex_color}", fill_type="solid" + start_color=f"FF{hex_color}", + end_color=f"FF{hex_color}", + fill_type="solid", ) if fmt.get("font_color"): hex_color = fmt["font_color"].lstrip("#") @@ -1028,7 +1064,9 @@ def add_conditional_format(self, workbook: Workbook, sheet: str, rule: JSONDict) rule_obj.priority = priority ws.conditional_formatting.add(range_ref, rule_obj) - def add_data_validation(self, workbook: Workbook, sheet: str, validation: JSONDict) -> None: + def add_data_validation( + self, workbook: Workbook, sheet: str, validation: JSONDict + ) -> None: ws = workbook[sheet] v = validation.get("validation", validation) dv = DataValidation( @@ -1105,7 +1143,9 @@ def add_comment(self, workbook: Workbook, sheet: str, comment: JSONDict) -> None c = c_obj c.comment = Comment(text, author) - def add_named_range(self, workbook: Workbook, sheet: str, named_range: JSONDict) -> None: + def add_named_range( + self, workbook: Workbook, sheet: str, named_range: JSONDict + ) -> None: from openpyxl.workbook.defined_name import DefinedName data = named_range.get("named_range", named_range) @@ -1119,7 +1159,11 @@ def add_named_range(self, workbook: Workbook, sheet: str, named_range: JSONDict) refers_to_str = str(refers_to) dn = DefinedName( str(name), - attr_text=(f"={refers_to_str}" if not refers_to_str.startswith("=") else refers_to_str), + attr_text=( + f"={refers_to_str}" + if not refers_to_str.startswith("=") + else refers_to_str + ), ) if scope == "sheet": ws = workbook[sheet] @@ -1174,7 +1218,8 @@ def add_table(self, workbook: Workbook, sheet: str, table: JSONDict) -> None: inferred.append("" if v is None else str(v)) if inferred: tbl.tableColumns = [ - TableColumn(id=i + 1, name=str(col)) for i, col in enumerate(inferred) + TableColumn(id=i + 1, name=str(col)) + for i, col in enumerate(inferred) ] except Exception: # Best-effort: if we can't infer column names from header cells, @@ -1187,7 +1232,9 @@ def add_table(self, workbook: Workbook, sheet: str, table: JSONDict) -> None: ws = workbook[sheet] ws.add_table(tbl) - def set_freeze_panes(self, workbook: Workbook, sheet: str, settings: JSONDict) -> None: + def set_freeze_panes( + self, workbook: Workbook, sheet: str, settings: JSONDict + ) -> None: ws = workbook[sheet] cfg = settings.get("freeze", settings) mode = cfg.get("mode") @@ -1210,3 +1257,151 @@ def set_freeze_panes(self, workbook: Workbook, sheet: str, settings: JSONDict) - if cfg.get("active_pane") is not None: pane.activePane = cfg["active_pane"] pane.state = "split" + + def read_sheet_protection(self, workbook: Workbook, sheet: str) -> JSONDict: + prot = workbook[sheet].protection + return { + "protected": bool(prot.sheet), + "password_hash_present": bool(prot.password), + "format_cells": prot.formatCells, + "insert_rows": prot.insertRows, + "select_locked_cells": prot.selectLockedCells, + "select_unlocked_cells": prot.selectUnlockedCells, + "sort": prot.sort, + "auto_filter": prot.autoFilter, + } + + def set_sheet_protection( + self, workbook: Workbook, sheet: str, settings: JSONDict + ) -> None: + cfg = settings.get("protection", settings) + prot = workbook[sheet].protection + if cfg.get("protected") is not None: + prot.sheet = bool(cfg.get("protected")) + if cfg.get("format_cells") is not None: + prot.formatCells = bool(cfg["format_cells"]) + if cfg.get("insert_rows") is not None: + prot.insertRows = bool(cfg["insert_rows"]) + if cfg.get("select_locked_cells") is not None: + prot.selectLockedCells = bool(cfg["select_locked_cells"]) + if cfg.get("select_unlocked_cells") is not None: + prot.selectUnlockedCells = bool(cfg["select_unlocked_cells"]) + if cfg.get("sort") is not None: + prot.sort = bool(cfg["sort"]) + if cfg.get("auto_filter") is not None: + prot.autoFilter = bool(cfg["auto_filter"]) + password = cfg.get("password") + if password: + prot.set_password(str(password)) + + def read_page_setup(self, workbook: Workbook, sheet: str) -> JSONDict: + ws = workbook[sheet] + ps = ws.page_setup + return { + "orientation": ps.orientation, + "fit_to_width": ps.fitToWidth, + "fit_to_height": ps.fitToHeight, + "scale": ps.scale, + "print_title_rows": ws.print_title_rows, + "header_center": ws.oddHeader.center.text if ws.oddHeader.center else None, + "footer_center": ws.oddFooter.center.text if ws.oddFooter.center else None, + } + + def set_page_setup( + self, workbook: Workbook, sheet: str, settings: JSONDict + ) -> None: + cfg = settings.get("page_setup", settings) + ws = workbook[sheet] + ps = ws.page_setup + if cfg.get("orientation") is not None: + ps.orientation = str(cfg["orientation"]) + if cfg.get("fit_to_width") is not None: + ps.fitToWidth = int(cfg["fit_to_width"]) + if cfg.get("fit_to_height") is not None: + ps.fitToHeight = int(cfg["fit_to_height"]) + if cfg.get("scale") is not None: + ps.scale = int(cfg["scale"]) + if cfg.get("print_title_rows") is not None: + ws.print_title_rows = str(cfg["print_title_rows"]) + if cfg.get("header_center") is not None: + ws.oddHeader.center.text = str(cfg["header_center"]) + if cfg.get("footer_center") is not None: + ws.oddFooter.center.text = str(cfg["footer_center"]) + + def read_chart_anchors(self, workbook: Workbook, sheet: str) -> list[JSONDict]: + from openpyxl.chart._chart import ChartBase + from openpyxl.drawing.spreadsheet_drawing import TwoCellAnchor + from openpyxl.utils.cell import get_column_letter + + def _cell(marker: Any) -> str | None: + if marker is None: + return None + return f"{get_column_letter(marker.col + 1)}{marker.row + 1}" + + results: list[JSONDict] = [] + for chart in workbook[sheet]._charts: + if not isinstance(chart, ChartBase): + continue + anchor = getattr(chart, "anchor", None) + anchor_type = type(anchor).__name__ if anchor is not None else None + from_ref = ( + _cell(getattr(anchor, "_from", None)) if anchor is not None else None + ) + to_ref = ( + _cell(getattr(anchor, "to", None)) + if isinstance(anchor, TwoCellAnchor) + else None + ) + normalized_type = type(chart).__name__.replace("Chart", "").lower() or None + if isinstance(normalized_type, str): + normalized_type = normalized_type or None + results.append( + { + "type": normalized_type, + "anchor_type": "twoCell" + if isinstance(anchor, TwoCellAnchor) + else ("oneCell" if anchor_type == "OneCellAnchor" else None), + "from": from_ref, + "to": to_ref, + } + ) + return results + + def add_chart_with_anchor( + self, workbook: Workbook, sheet: str, chart: JSONDict + ) -> None: + from openpyxl.chart import BarChart, LineChart, Reference + from openpyxl.drawing.spreadsheet_drawing import AnchorMarker, TwoCellAnchor + from openpyxl.utils.cell import coordinate_to_tuple + + cfg = chart.get("chart", chart) + chart_type = str(cfg.get("type") or "bar").lower() + data_ref = str(cfg.get("data_ref") or "") + if not data_ref: + raise ValueError("add_chart_with_anchor requires data_ref") + + ws = workbook[sheet] + values = Reference( + ws, range_string=data_ref if "!" in data_ref else f"{ws.title}!{data_ref}" + ) + series_chart: Any + if chart_type == "line": + series_chart = LineChart() + else: + series_chart = BarChart() + series_chart.add_data(values, titles_from_data=False) + cats = cfg.get("categories_ref") + if cats: + cat_ref = Reference( + ws, range_string=cats if "!" in cats else f"{ws.title}!{cats}" + ) + series_chart.set_categories(cat_ref) + + from_row, from_col = coordinate_to_tuple(str(cfg.get("from") or "B2")) + to_row, to_col = coordinate_to_tuple(str(cfg.get("to") or "H12")) + anchor = TwoCellAnchor( + _from=AnchorMarker(col=from_col - 1, colOff=0, row=from_row - 1, rowOff=0), + to=AnchorMarker(col=to_col - 1, colOff=0, row=to_row - 1, rowOff=0), + ) + series_chart.anchor = anchor + ws.add_chart(series_chart) diff --git a/src/excelbench/harness/adapters/wolfxl_adapter.py b/src/excelbench/harness/adapters/wolfxl_adapter.py index d57557f..da8fe01 100644 --- a/src/excelbench/harness/adapters/wolfxl_adapter.py +++ b/src/excelbench/harness/adapters/wolfxl_adapter.py @@ -1,28 +1,19 @@ -"""wolfxl — hybrid Rust adapter: calamine (read) + rust_xlsxwriter (write). - -Combines the fastest Rust Excel reader (calamine with style support) and the -fastest Rust writer (rust_xlsxwriter) into a single full-fidelity R+W adapter. -""" +"""Adapter for WolfXL's public openpyxl-compatible Python API.""" import posixpath import zipfile +from datetime import date, datetime from pathlib import Path from typing import Any from xml.etree import ElementTree as ET +import wolfxl + from excelbench.harness.adapters.base import ExcelAdapter -from excelbench.harness.adapters.rust_adapter_utils import ( - border_to_dict, - cell_value_from_payload, - dict_to_border, - dict_to_format, - format_to_dict, - get_rust_backend_version, - payload_from_cell_value, - rust_xlsxwriter_row_index, -) from excelbench.models import ( + BorderEdge, BorderInfo, + BorderStyle, CellFormat, CellType, CellValue, @@ -31,37 +22,80 @@ JSONDict = dict[str, Any] -try: - import wolfxl._rust as _excelbench_rust -except ImportError as e: # pragma: no cover - raise ImportError("wolfxl._rust unavailable — wolfxl adapter requires it") from e +# Formulas that produce known error values. WolfXL writes formulas rather than +# cached error values, so preserve the benchmark's normal error-write contract. +ERROR_FORMULA_MAP = { + "=1/0": "#DIV/0!", + "=NA()": "#N/A", + '="text"+1': "#VALUE!", +} -if getattr(_excelbench_rust, "CalamineStyledBook", None) is None: # pragma: no cover - raise ImportError("wolfxl._rust built without calamine backend") -if ( - getattr(_excelbench_rust, "NativeWorkbook", None) is None - and getattr(_excelbench_rust, "RustXlsxWriterBook", None) is None -): # pragma: no cover - raise ImportError("wolfxl._rust built without a native writer backend") +def _color_to_hex(color: Any) -> str | None: + """Return a normalized RGB value from an openpyxl-compatible color.""" + if color is None: + return None -def _writer_class(rust_module: Any) -> Any: - """Return the current WolfXL writer class, with legacy fallback.""" - - native = getattr(rust_module, "NativeWorkbook", None) - if native is not None: - return native - return getattr(rust_module, "RustXlsxWriterBook") + rgb = getattr(color, "rgb", None) + if isinstance(rgb, str) and len(rgb) >= 6: + return f"#{rgb[2:]}" if len(rgb) == 8 else f"#{rgb}" + + value = getattr(rgb, "value", None) + if isinstance(value, str) and len(value) >= 6: + return f"#{value[2:]}" if len(value) == 8 else f"#{value}" + return None + + +def _col_letter(index: int) -> str: + """Return the one-based column index as an A1 column letter.""" + result = "" + while index > 0: + index, rem = divmod(index - 1, 26) + result = chr(65 + rem) + result + return result + + +def _cell_value_from_wolfxl_cell(cell: Any) -> CellValue: + """Convert a WolfXL cell proxy into ExcelBench's typed value model.""" + value = getattr(cell, "value", None) + if value is None: + return CellValue(type=CellType.BLANK) + if isinstance(value, bool): + return CellValue(type=CellType.BOOLEAN, value=value) + if isinstance(value, (int, float)): + return CellValue(type=CellType.NUMBER, value=value) + if isinstance(value, date) and not isinstance(value, datetime): + return CellValue(type=CellType.DATE, value=value) + if isinstance(value, datetime): + if ( + value.hour == 0 + and value.minute == 0 + and value.second == 0 + and value.microsecond == 0 + ): + return CellValue(type=CellType.DATE, value=value.date()) + return CellValue(type=CellType.DATETIME, value=value) + if isinstance(value, str): + if value in {"#N/A", "#NULL!", "#NAME?", "#REF!"} or ( + value.startswith("#") and value.endswith("!") + ): + return CellValue(type=CellType.ERROR, value=value) + if getattr(cell, "data_type", None) == "f" or value.startswith("="): + formula = value if value.startswith("=") else f"={value}" + if formula in ERROR_FORMULA_MAP: + return CellValue(type=CellType.ERROR, value=ERROR_FORMULA_MAP[formula]) + return CellValue(type=CellType.FORMULA, value=value, formula=formula) + return CellValue(type=CellType.STRING, value=value) + return CellValue(type=CellType.STRING, value=str(value)) def _read_images_from_xlsx(path: Path, sheet_name: str) -> list[JSONDict]: """Read image anchors from OOXML drawing parts. - WolfXL 2.0's public read model exposes cell-level values/styles through - CalamineStyledBook; image metadata still lives in OOXML drawing parts, so - the benchmark adapter reads those parts directly. + WolfXL exposes images through its openpyxl-compatible API, but fixture image + paths remain OOXML package paths. Reading drawing relationships directly + preserves those package-relative paths for ExcelBench comparison. """ - ns = { "main": "http://schemas.openxmlformats.org/spreadsheetml/2006/main", "rel": "http://schemas.openxmlformats.org/package/2006/relationships", @@ -75,13 +109,11 @@ def read_xml(zf: zipfile.ZipFile, name: str) -> ET.Element: def rel_targets(zf: zipfile.ZipFile, rels_path: str) -> dict[str, str]: root = read_xml(zf, rels_path) - out: dict[str, str] = {} - for rel in root.findall("rel:Relationship", ns): - rid = rel.attrib.get("Id") - target = rel.attrib.get("Target") - if rid and target: - out[rid] = target - return out + return { + rel_id: target + for rel in root.findall("rel:Relationship", ns) + if (rel_id := rel.attrib.get("Id")) and (target := rel.attrib.get("Target")) + } def resolve(base_part: str, target: str) -> str: if target.startswith("/"): @@ -93,13 +125,9 @@ def rels_for(part: str) -> str: return posixpath.join(directory, "_rels", f"{filename}.rels") def cell_from_marker(marker: ET.Element) -> str: - col = int(marker.findtext("xdr:col", "0", ns)) + 1 + column = int(marker.findtext("xdr:col", "0", ns)) + 1 row = int(marker.findtext("xdr:row", "0", ns)) + 1 - letters = "" - while col: - col, rem = divmod(col - 1, 26) - letters = chr(65 + rem) + letters - return f"{letters}{row}" + return f"{_col_letter(column)}{row}" with zipfile.ZipFile(path) as zf: workbook = read_xml(zf, "xl/workbook.xml") @@ -108,8 +136,8 @@ def cell_from_marker(marker: ET.Element) -> str: for sheet in workbook.findall("main:sheets/main:sheet", ns): if sheet.attrib.get("name") != sheet_name: continue - rid = sheet.attrib.get(f"{{{ns['r']}}}id") - target = workbook_rels.get(str(rid)) if rid else None + rel_id = sheet.attrib.get(f"{{{ns['r']}}}id") + target = workbook_rels.get(str(rel_id)) if rel_id else None if target: sheet_part = resolve("xl/workbook.xml", target) break @@ -131,7 +159,6 @@ def cell_from_marker(marker: ET.Element) -> str: drawing_rels = rel_targets(zf, rels_for(drawing_part)) except KeyError: drawing_rels = {} - for anchor_tag, anchor_name in ( ("xdr:oneCellAnchor", "oneCell"), ("xdr:twoCellAnchor", "twoCell"), @@ -143,38 +170,79 @@ def cell_from_marker(marker: ET.Element) -> str: continue embed = blip.attrib.get(f"{{{ns['r']}}}embed") media_target = drawing_rels.get(str(embed)) if embed else None - if not media_target: - continue - media_part = resolve(drawing_part, media_target) - images.append( - { - "cell": cell_from_marker(marker), - "path": f"/{media_part}", - "anchor": anchor_name, - } - ) + if media_target: + images.append( + { + "cell": cell_from_marker(marker), + "path": f"/{resolve(drawing_part, media_target)}", + "anchor": anchor_name, + } + ) return images class WolfxlAdapter(ExcelAdapter): - """Hybrid adapter: calamine-styled reads + rust_xlsxwriter writes.""" + """Read and write XLSX workbooks through WolfXL's public Python API.""" def __init__(self) -> None: - # Python-side cell cache: avoids FFI on repeated reads of the same cell. - # Keyed by (workbook_id, sheet, cell) → CellValue. - self._cell_cache: dict[tuple[int, str, str], CellValue] = {} self._workbook_paths: dict[int, Path] = {} + @classmethod + def is_available(cls) -> bool: + """Return whether WolfXL 2's required public API is importable.""" + try: + from wolfxl import ( + Alignment, + Border, + Font, + PatternFill, + Side, + Workbook, + load_workbook, + ) + from wolfxl.chart import BarChart, LineChart, Reference + from wolfxl.comments import Comment + from wolfxl.drawing.image import Image + from wolfxl.drawing.spreadsheet_drawing import AnchorMarker, TwoCellAnchor + from wolfxl.formatting.rule import ColorScaleRule, DataBarRule, FormulaRule + from wolfxl.worksheet.datavalidation import DataValidation + from wolfxl.worksheet.hyperlink import Hyperlink + from wolfxl.worksheet.table import Table, TableColumn, TableStyleInfo + + required = ( + Alignment, + AnchorMarker, + BarChart, + Border, + ColorScaleRule, + Comment, + DataBarRule, + DataValidation, + Font, + FormulaRule, + Hyperlink, + Image, + LineChart, + PatternFill, + Reference, + Side, + Table, + TableColumn, + TableStyleInfo, + TwoCellAnchor, + Workbook, + load_workbook, + ) + return bool(required) and int(str(wolfxl.__version__).split(".", 1)[0]) >= 2 + except (ImportError, ValueError): + return False + @property def info(self) -> LibraryInfo: - cal_ver = get_rust_backend_version("calamine") - rxw_ver = get_rust_backend_version("rust_xlsxwriter") - if rxw_ver == "unknown": - rxw_ver = get_rust_backend_version("native") return LibraryInfo( name="wolfxl", - version=f"cal={cal_ver}+rxw={rxw_ver}", - language="rust", + version=str(wolfxl.__version__), + language="python", capabilities={"read", "write", "modify"}, ) @@ -183,184 +251,420 @@ def supported_read_extensions(self) -> set[str]: return {".xlsx"} # ========================================================================= - # Read — delegates to CalamineStyledBook + # Read operations # ========================================================================= def open_workbook(self, path: Path) -> Any: - import wolfxl._rust as rust - - m: Any = rust - workbook = getattr(m, "CalamineStyledBook").open(str(path)) + workbook = wolfxl.load_workbook(path, data_only=False) self._workbook_paths[id(workbook)] = path return workbook def close_workbook(self, workbook: Any) -> None: - # Evict cached cells for this workbook. - wb_id = id(workbook) - self._cell_cache = {k: v for k, v in self._cell_cache.items() if k[0] != wb_id} - self._workbook_paths.pop(wb_id, None) + self._workbook_paths.pop(id(workbook), None) + close = getattr(workbook, "close", None) + if callable(close): + close() def get_sheet_names(self, workbook: Any) -> list[str]: - return [str(name) for name in workbook.sheet_names()] - - def read_cell_value(self, workbook: Any, sheet: str, cell: str) -> CellValue: - key = (id(workbook), sheet, cell) - cached = self._cell_cache.get(key) - if cached is not None: - return cached - payload = workbook.read_cell_value(sheet, cell) - if not isinstance(payload, dict): - result = CellValue(type=CellType.STRING, value=str(payload)) - else: - result = cell_value_from_payload(payload) - self._cell_cache[key] = result - return result + return [str(name) for name in workbook.sheetnames] def read_sheet_values( - self, - workbook: Any, - sheet: str, - cell_range: str | None = None, + self, workbook: Any, sheet: str, cell_range: str | None = None ) -> list[list[CellValue]]: - """Bulk read all values from a sheet via CalamineStyledBook.read_sheet_values().""" - raw = workbook.read_sheet_values(sheet, cell_range) - return [ - [ - cell_value_from_payload(v) - if isinstance(v, dict) - else CellValue(type=CellType.BLANK) - for v in row - ] - for row in raw - ] + worksheet = workbook[sheet] + rows = worksheet[cell_range] if cell_range else worksheet.iter_rows() + return [[_cell_value_from_wolfxl_cell(cell) for cell in row] for row in rows] - def read_sheet_values_raw( - self, - workbook: Any, - sheet: str, - cell_range: str | None = None, - ) -> list[list[Any]]: - """Return raw Rust FFI output without cell_value_from_payload() wrapping.""" - result: list[list[Any]] = workbook.read_sheet_values(sheet, cell_range) - return result + def read_cell_value(self, workbook: Any, sheet: str, cell: str) -> CellValue: + return _cell_value_from_wolfxl_cell(workbook[sheet][cell]) def read_cell_format(self, workbook: Any, sheet: str, cell: str) -> CellFormat: - payload = workbook.read_cell_format(sheet, cell) - if not isinstance(payload, dict) or not payload: - return CellFormat() - return dict_to_format(payload) + current = workbook[sheet][cell] + font = current.font + fill = current.fill + alignment = current.alignment + return CellFormat( + bold=font.bold or None, + italic=font.italic or None, + underline=font.underline or None, + strikethrough=font.strike or None, + font_name=font.name or None, + font_size=font.size or None, + font_color=_color_to_hex(getattr(font, "color", None)), + bg_color=( + _color_to_hex(getattr(fill, "fgColor", None)) + if getattr(fill, "patternType", None) == "solid" + else None + ), + number_format=current.number_format or None, + h_align=getattr(alignment, "horizontal", None) or None, + v_align=getattr(alignment, "vertical", None) or None, + wrap=getattr(alignment, "wrap_text", None) or None, + rotation=( + getattr(alignment, "text_rotation", None) + if getattr(alignment, "text_rotation", None) not in (0, None) + else None + ), + indent=getattr(alignment, "indent", None) or None, + ) def read_cell_border(self, workbook: Any, sheet: str, cell: str) -> BorderInfo: - payload = workbook.read_cell_border(sheet, cell) - if not isinstance(payload, dict) or not payload: - return BorderInfo() - return dict_to_border(payload) + border = workbook[sheet][cell].border + + def parse_side(side: Any) -> BorderEdge | None: + if side is None or getattr(side, "style", None) is None: + return None + style_map = { + "thin": BorderStyle.THIN, + "medium": BorderStyle.MEDIUM, + "thick": BorderStyle.THICK, + "double": BorderStyle.DOUBLE, + "dashed": BorderStyle.DASHED, + "dotted": BorderStyle.DOTTED, + "hair": BorderStyle.HAIR, + "mediumDashed": BorderStyle.MEDIUM_DASHED, + "dashDot": BorderStyle.DASH_DOT, + "mediumDashDot": BorderStyle.MEDIUM_DASH_DOT, + "dashDotDot": BorderStyle.DASH_DOT_DOT, + "mediumDashDotDot": BorderStyle.MEDIUM_DASH_DOT_DOT, + "slantDashDot": BorderStyle.SLANT_DASH_DOT, + } + return BorderEdge( + style=style_map.get(side.style, BorderStyle.THIN), + color=_color_to_hex(getattr(side, "color", None)) or "#000000", + ) + + return BorderInfo( + top=parse_side(border.top), + bottom=parse_side(border.bottom), + left=parse_side(border.left), + right=parse_side(border.right), + diagonal_up=parse_side(border.diagonal) if border.diagonalUp else None, + diagonal_down=parse_side(border.diagonal) if border.diagonalDown else None, + ) def read_row_height(self, workbook: Any, sheet: str, row: int) -> float | None: - value = workbook.read_row_height(sheet, row) - if value is None: - return None - if isinstance(value, (int, float)): - return float(value) - return None + height = workbook[sheet].row_dimensions[row].height + return float(height) if isinstance(height, (int, float)) else None def read_column_width(self, workbook: Any, sheet: str, column: str) -> float | None: - value = workbook.read_column_width(sheet, column) - if value is None: + width = workbook[sheet].column_dimensions[column].width + try: + return float(width) if width is not None else None + except (TypeError, ValueError): return None - if isinstance(value, (int, float)): - return float(value) - return None + + # ========================================================================= + # Tier 2 reads + # ========================================================================= def read_merged_ranges(self, workbook: Any, sheet: str) -> list[str]: - result = workbook.read_merged_ranges(sheet) - if isinstance(result, list): - return [str(x) for x in result] - return [] + return [str(cell_range) for cell_range in workbook[sheet].merged_cells.ranges] def read_conditional_formats(self, workbook: Any, sheet: str) -> list[JSONDict]: - result = workbook.read_conditional_formats(sheet) - if isinstance(result, list): - return [dict(x) for x in result if isinstance(x, dict)] - return [] + conditional_formatting = workbook[sheet].conditional_formatting + rules_by_range = getattr(conditional_formatting, "_cf_rules", None) + if rules_by_range is None: + self.unsupported_operation( + "read_conditional_formats", + "WolfXL's installed compatibility layer does not expose conditional rules.", + ) + rules: list[JSONDict] = [] + for sqref, rule_list in rules_by_range.items(): + range_value = str(getattr(sqref, "sqref", sqref)) + for rule in rule_list: + entry: JSONDict = { + "range": range_value, + "rule_type": getattr(rule, "type", None), + "operator": getattr(rule, "operator", None), + "formula": rule.formula[0] + if getattr(rule, "formula", None) + else None, + "priority": getattr(rule, "priority", None), + "stop_if_true": getattr(rule, "stopIfTrue", None), + "format": {}, + } + dxf = getattr(rule, "dxf", None) + if dxf is not None: + if bg := _color_to_hex( + getattr(getattr(dxf, "fill", None), "fgColor", None) + ): + entry["format"]["bg_color"] = bg + if font_color := _color_to_hex( + getattr(getattr(dxf, "font", None), "color", None) + ): + entry["format"]["font_color"] = font_color + rules.append(entry) + return rules def read_data_validations(self, workbook: Any, sheet: str) -> list[JSONDict]: - result = workbook.read_data_validations(sheet) - if isinstance(result, list): - return [dict(x) for x in result if isinstance(x, dict)] - return [] - - def read_named_ranges(self, workbook: Any, sheet: str) -> list[JSONDict]: - result = workbook.read_named_ranges(sheet) - if isinstance(result, list): - return [dict(x) for x in result if isinstance(x, dict)] - return [] - - def read_tables(self, workbook: Any, sheet: str) -> list[JSONDict]: - result = workbook.read_tables(sheet) - if isinstance(result, list): - return [dict(x) for x in result if isinstance(x, dict)] - return [] + validations = getattr(workbook[sheet].data_validations, "dataValidation", None) + if validations is None: + self.unsupported_operation( + "read_data_validations", + "WolfXL's installed compatibility layer does not expose data validations.", + ) + return [ + { + "range": str(entry.sqref), + "validation_type": entry.type, + "operator": entry.operator or ("between" if entry.formula2 else None), + "formula1": entry.formula1, + "formula2": entry.formula2, + "allow_blank": entry.allow_blank, + "show_input": entry.showInputMessage, + "show_error": entry.showErrorMessage, + "prompt_title": entry.promptTitle, + "prompt": entry.prompt, + "error_title": entry.errorTitle, + "error": entry.error, + } + for entry in validations + ] def read_hyperlinks(self, workbook: Any, sheet: str) -> list[JSONDict]: - result = workbook.read_hyperlinks(sheet) - if isinstance(result, list): - return [dict(x) for x in result if isinstance(x, dict)] - return [] + links: list[JSONDict] = [] + for row in workbook[sheet].iter_rows(): + for cell in row: + hyperlink = cell.hyperlink + if hyperlink is None: + continue + if hyperlink.target and hyperlink.location: + target = f"{hyperlink.target}#{hyperlink.location}" + internal = False + elif hyperlink.target: + target = hyperlink.target + internal = False + else: + target = hyperlink.location + internal = True + links.append( + { + "cell": cell.coordinate, + "target": target, + "display": cell.value, + "tooltip": hyperlink.tooltip, + "internal": internal, + } + ) + return links def read_images(self, workbook: Any, sheet: str) -> list[JSONDict]: path = self._workbook_paths.get(id(workbook)) if path is None: - return [] - try: - return _read_images_from_xlsx(path, sheet) - except Exception: - return [] + self.unsupported_operation( + "read_images", + "Image package paths are available only for workbooks opened from a file.", + ) + return _read_images_from_xlsx(path, sheet) def read_pivot_tables(self, workbook: Any, sheet: str) -> list[JSONDict]: - return [] + pivots = getattr(workbook[sheet], "pivot_tables", None) + if pivots is None: + self.unsupported_operation( + "read_pivot_tables", + "WolfXL's installed compatibility layer does not expose pivot tables.", + ) + results: list[JSONDict] = [] + for pivot in pivots: + cache = getattr(pivot, "cache", None) + cache_source = getattr(cache, "cacheSource", None) + worksheet_source = getattr(cache_source, "worksheetSource", None) + source_ref = getattr(worksheet_source, "ref", None) + source_sheet = getattr(worksheet_source, "sheet", None) + if source_sheet and source_ref: + source_range = f"{source_sheet}!{source_ref}" + else: + source_range = source_ref or getattr(cache_source, "ref", None) + location = getattr(pivot, "location", None) + target_cell = getattr(location, "ref", None) or location + if target_cell and "!" not in str(target_cell): + target_cell = f"{sheet}!{target_cell}" + results.append( + { + "name": getattr(pivot, "name", None), + "source_range": source_range, + "target_cell": target_cell, + } + ) + return results def read_comments(self, workbook: Any, sheet: str) -> list[JSONDict]: - result = workbook.read_comments(sheet) - if isinstance(result, list): - return [dict(x) for x in result if isinstance(x, dict)] - return [] + comments: list[JSONDict] = [] + for row in workbook[sheet].iter_rows(): + for cell in row: + if cell.comment is not None: + comments.append( + { + "cell": cell.coordinate, + "text": cell.comment.text, + "author": cell.comment.author, + "threaded": False, + } + ) + return comments def read_freeze_panes(self, workbook: Any, sheet: str) -> JSONDict: - return dict(workbook.read_freeze_panes(sheet)) + worksheet = workbook[sheet] + result: JSONDict = {} + if worksheet.freeze_panes: + result["mode"] = "freeze" + result["top_left_cell"] = str(worksheet.freeze_panes) + pane = getattr(worksheet.sheet_view, "pane", None) + if pane is not None and pane.state == "split" and (pane.xSplit or pane.ySplit): + result["mode"] = "split" + result["x_split"] = int(pane.xSplit) if pane.xSplit is not None else None + result["y_split"] = int(pane.ySplit) if pane.ySplit is not None else None + if pane.topLeftCell: + result["top_left_cell"] = pane.topLeftCell + if pane.activePane: + result["active_pane"] = pane.activePane + return result # ========================================================================= - # Write — delegates to NativeWorkbook (WolfXL 2.0+) or RustXlsxWriterBook - # on older WolfXL releases. + # Tier 3 reads # ========================================================================= - def create_workbook(self) -> Any: - import wolfxl._rust as rust + def read_named_ranges(self, workbook: Any, sheet: str) -> list[JSONDict]: + def normalize_refers_to(value: Any) -> str: + raw = str(value or "").lstrip("=") + if "!" not in raw: + return raw + sheet_name, address = raw.split("!", 1) + if sheet_name.startswith("'") and sheet_name.endswith("'"): + sheet_name = sheet_name[1:-1].replace("''", "'") + return f"{sheet_name}!{address}" + + results: list[JSONDict] = [] + seen: set[tuple[str, str, str]] = set() + worksheet = workbook[sheet] + sheet_id = workbook.worksheets.index(worksheet) + for key in workbook.defined_names: + name = workbook.defined_names.get(key) + if name is None: + continue + local_sheet_id = getattr(name, "localSheetId", None) + if local_sheet_id is not None and int(local_sheet_id) != sheet_id: + continue + scope = "sheet" if local_sheet_id is not None else "workbook" + item: JSONDict = { + "name": str(getattr(name, "name", key)), + "scope": scope, + "refers_to": normalize_refers_to(getattr(name, "attr_text", None)), + } + signature = (str(item["name"]), str(item["scope"]), str(item["refers_to"])) + if signature not in seen: + seen.add(signature) + results.append(item) + for key in worksheet.defined_names: + name = worksheet.defined_names.get(key) + if name is None: + continue + item = { + "name": str(getattr(name, "name", key)), + "scope": "sheet", + "refers_to": normalize_refers_to(getattr(name, "attr_text", None)), + } + signature = (str(item["name"]), str(item["scope"]), str(item["refers_to"])) + if signature not in seen: + seen.add(signature) + results.append(item) + return results - m: Any = rust - return _writer_class(m)() + def read_tables(self, workbook: Any, sheet: str) -> list[JSONDict]: + worksheet = workbook[sheet] + tables = getattr(worksheet, "tables", None) + if tables is None: + self.unsupported_operation( + "read_tables", + "WolfXL's installed compatibility layer does not expose tables.", + ) + results: list[JSONDict] = [] + for table in tables.values(): + columns = [ + str(column.name) + for column in (getattr(table, "tableColumns", []) or []) + if column.name is not None + ] + if not columns: + from wolfxl.utils.cell import range_boundaries + + min_col, min_row, max_col, _ = range_boundaries(str(table.ref)) + columns = [ + "" + if worksheet.cell(row=min_row, column=column).value is None + else str(worksheet.cell(row=min_row, column=column).value) + for column in range(min_col, max_col + 1) + ] + results.append( + { + "name": getattr(table, "displayName", None) + or getattr(table, "name", None), + "ref": getattr(table, "ref", None), + "header_row": getattr(table, "headerRowCount", 1) != 0, + "totals_row": (getattr(table, "totalsRowCount", 0) or 0) > 0, + "style": ( + table.tableStyleInfo.name + if getattr(table, "tableStyleInfo", None) + else None + ), + "columns": columns, + "autofilter": getattr(table, "autoFilter", None) is not None, + } + ) + return results - def add_sheet(self, workbook: Any, name: str) -> None: - workbook.add_sheet(name) + # ========================================================================= + # Write operations + # ========================================================================= - def write_cell_value(self, workbook: Any, sheet: str, cell: str, value: CellValue) -> None: - payload = payload_from_cell_value(value) - workbook.write_cell_value(sheet, cell, payload) + def create_workbook(self) -> Any: + workbook = wolfxl.Workbook() + if workbook.sheetnames: + workbook.remove(workbook.active) + return workbook + + def add_sheet(self, workbook: Any, name: str) -> None: + workbook.create_sheet(name) def write_sheet_values( - self, - workbook: Any, - sheet: str, - start_cell: str, - values: list[list[Any]], + self, workbook: Any, sheet: str, start_cell: str, values: list[list[Any]] ) -> None: - """Bulk write a grid of values via the native writer.""" - workbook.write_sheet_values(sheet, start_cell, values) + from wolfxl.utils.cell import column_index_from_string, coordinate_from_string + + column, row = coordinate_from_string(start_cell) + worksheet = workbook[sheet] + start_column = column_index_from_string(column) + for row_offset, values_row in enumerate(values): + for column_offset, value in enumerate(values_row): + if value is not None: + worksheet.cell( + row=row + row_offset, + column=start_column + column_offset, + value=value, + ) - def write_cell_format(self, workbook: Any, sheet: str, cell: str, format: CellFormat) -> None: - d = format_to_dict(format) - if d: - workbook.write_cell_format(sheet, cell, d) + def write_cell_value( + self, workbook: Any, sheet: str, cell: str, value: CellValue + ) -> None: + target = workbook[sheet][cell] + if value.type == CellType.BLANK: + target.value = None + elif value.type == CellType.FORMULA: + target.value = value.formula or value.value + elif value.type == CellType.ERROR: + error_formulas = { + "#DIV/0!": "=1/0", + "#N/A": "=NA()", + "#VALUE!": '="text"+1', + "#REF!": "=#REF!", + "#NAME?": "=_undefined_name_", + "#NUM!": "=SQRT(-1)", + "#NULL!": "=A1:A2 B1:B2", + } + target.value = error_formulas.get(str(value.value), value.value) + else: + target.value = value.value def write_sheet_formats( self, @@ -369,13 +673,60 @@ def write_sheet_formats( start_cell: str, formats: list[list[dict[str, Any] | None]], ) -> None: - """Bulk write a grid of format dicts via the native writer.""" - workbook.write_sheet_formats(sheet, start_cell, formats) + from wolfxl.utils.cell import column_index_from_string, coordinate_from_string + + column, row = coordinate_from_string(start_cell) + start_column = column_index_from_string(column) + for row_offset, format_row in enumerate(formats): + for column_offset, format_data in enumerate(format_row): + if format_data is not None: + self.write_cell_format( + workbook, + sheet, + f"{_col_letter(start_column + column_offset)}{row + row_offset}", + CellFormat(**format_data), + ) - def write_cell_border(self, workbook: Any, sheet: str, cell: str, border: BorderInfo) -> None: - d = border_to_dict(border) - if d: - workbook.write_cell_border(sheet, cell, d) + def write_cell_format( + self, workbook: Any, sheet: str, cell: str, format: CellFormat + ) -> None: + from wolfxl import Alignment, Color, Font, PatternFill + + target = workbook[sheet][cell] + font_kwargs: JSONDict = {} + for field, attr in ( + ("bold", "bold"), + ("italic", "italic"), + ("underline", "underline"), + ("strikethrough", "strike"), + ("font_name", "name"), + ("font_size", "size"), + ): + if (field_value := getattr(format, field)) is not None: + font_kwargs[attr] = field_value + if format.font_color is not None: + font_kwargs["color"] = Color(rgb=f"FF{format.font_color.lstrip('#')}") + if font_kwargs: + target.font = Font(**font_kwargs) + if format.bg_color is not None: + color = f"FF{format.bg_color.lstrip('#')}" + target.fill = PatternFill( + start_color=color, end_color=color, fill_type="solid" + ) + if format.number_format is not None: + target.number_format = format.number_format + alignment_kwargs: JSONDict = {} + for field, attr in ( + ("h_align", "horizontal"), + ("v_align", "vertical"), + ("wrap", "wrap_text"), + ("rotation", "text_rotation"), + ("indent", "indent"), + ): + if (field_value := getattr(format, field)) is not None: + alignment_kwargs[attr] = field_value + if alignment_kwargs: + target.alignment = Alignment(**alignment_kwargs) def write_sheet_borders( self, @@ -384,64 +735,442 @@ def write_sheet_borders( start_cell: str, borders: list[list[dict[str, Any] | None]], ) -> None: - """Bulk write a grid of border dicts via the native writer.""" - workbook.write_sheet_borders(sheet, start_cell, borders) + from wolfxl.utils.cell import column_index_from_string, coordinate_from_string + + from excelbench.harness.adapters.rust_adapter_utils import dict_to_border + + column, row = coordinate_from_string(start_cell) + start_column = column_index_from_string(column) + for row_offset, border_row in enumerate(borders): + for column_offset, border_data in enumerate(border_row): + if border_data is not None: + self.write_cell_border( + workbook, + sheet, + f"{_col_letter(start_column + column_offset)}{row + row_offset}", + dict_to_border(border_data), + ) - def set_row_height(self, workbook: Any, sheet: str, row: int, height: float) -> None: - workbook.set_row_height(sheet, rust_xlsxwriter_row_index(row), height) + def write_cell_border( + self, workbook: Any, sheet: str, cell: str, border: BorderInfo + ) -> None: + from wolfxl import Border, Color, Side + + def make_side(edge: BorderEdge | None) -> Any: + if edge is None: + return Side() + style_map = { + BorderStyle.NONE: None, + BorderStyle.THIN: "thin", + BorderStyle.MEDIUM: "medium", + BorderStyle.THICK: "thick", + BorderStyle.DOUBLE: "double", + BorderStyle.DASHED: "dashed", + BorderStyle.DOTTED: "dotted", + BorderStyle.HAIR: "hair", + BorderStyle.MEDIUM_DASHED: "mediumDashed", + BorderStyle.DASH_DOT: "dashDot", + BorderStyle.MEDIUM_DASH_DOT: "mediumDashDot", + BorderStyle.DASH_DOT_DOT: "dashDotDot", + BorderStyle.MEDIUM_DASH_DOT_DOT: "mediumDashDotDot", + BorderStyle.SLANT_DASH_DOT: "slantDashDot", + } + style = style_map.get(edge.style) + return ( + Side() + if style is None + else Side(style=style, color=Color(rgb=f"FF{edge.color.lstrip('#')}")) + ) + + diagonal = make_side(border.diagonal_up or border.diagonal_down) + workbook[sheet][cell].border = Border( + left=make_side(border.left), + right=make_side(border.right), + top=make_side(border.top), + bottom=make_side(border.bottom), + diagonal=diagonal, + diagonalUp=border.diagonal_up is not None, + diagonalDown=border.diagonal_down is not None, + ) + + def set_row_height( + self, workbook: Any, sheet: str, row: int, height: float + ) -> None: + workbook[sheet].row_dimensions[row].height = height - def set_column_width(self, workbook: Any, sheet: str, column: str, width: float) -> None: - workbook.set_column_width(sheet, column, width) + def set_column_width( + self, workbook: Any, sheet: str, column: str, width: float + ) -> None: + workbook[sheet].column_dimensions[column].width = width + + # ========================================================================= + # Tier 2 writes + # ========================================================================= def merge_cells(self, workbook: Any, sheet: str, cell_range: str) -> None: - workbook.merge_cells(sheet, cell_range) + workbook[sheet].merge_cells(cell_range) def add_conditional_format(self, workbook: Any, sheet: str, rule: JSONDict) -> None: - workbook.add_conditional_format(sheet, rule.get("cf_rule", rule)) - - def add_data_validation(self, workbook: Any, sheet: str, validation: JSONDict) -> None: - workbook.add_data_validation(sheet, validation) + from wolfxl import Font, PatternFill + from wolfxl.formatting.rule import ( + CellIsRule, + ColorScaleRule, + DataBarRule, + FormulaRule, + ) - def add_named_range(self, workbook: Any, sheet: str, named_range: JSONDict) -> None: - workbook.add_named_range(sheet, named_range) + cfg = rule.get("cf_rule", rule) + range_ref = cfg.get("range") + if not isinstance(range_ref, str): + raise ValueError("add_conditional_format requires range") + fmt = cfg.get("format") or {} + fill = ( + PatternFill( + start_color=f"FF{str(fmt['bg_color']).lstrip('#')}", + end_color=f"FF{str(fmt['bg_color']).lstrip('#')}", + fill_type="solid", + ) + if fmt.get("bg_color") + else None + ) + font = ( + Font(color=f"FF{str(fmt['font_color']).lstrip('#')}") + if fmt.get("font_color") + else None + ) + rule_type = cfg.get("rule_type") + formula = cfg.get("formula") + if rule_type in {"cellIs", "cellIsRule"}: + rule_obj: Any = CellIsRule( + operator=cfg.get("operator"), + formula=[str(formula)], + fill=fill, + font=font, + stopIfTrue=cfg.get("stop_if_true", False), + ) + elif rule_type in {"expression", "formula"}: + rule_obj = FormulaRule( + formula=[str(formula)], + fill=fill, + font=font, + stopIfTrue=cfg.get("stop_if_true", False), + ) + elif rule_type == "colorScale": + rule_obj = ColorScaleRule( + start_type="min", + start_color="FFAA0000", + mid_type="percentile", + mid_value=50, + mid_color="FFFFFF00", + end_type="max", + end_color="FF00AA00", + ) + elif rule_type == "dataBar": + rule_obj = DataBarRule( + start_type="min", end_type="max", color="FF638EC6", showValue=True + ) + else: + self.unsupported_operation( + "add_conditional_format", + f"WolfXL adapter does not support rule type {rule_type!r}.", + ) + if cfg.get("priority") is not None: + rule_obj.priority = cfg["priority"] + workbook[sheet].conditional_formatting.add(range_ref, rule_obj) - def add_table(self, workbook: Any, sheet: str, table: JSONDict) -> None: - workbook.add_table(sheet, table.get("table", table)) + def add_data_validation( + self, workbook: Any, sheet: str, validation: JSONDict + ) -> None: + from wolfxl.worksheet.datavalidation import DataValidation + + cfg = validation.get("validation", validation) + cell_range = cfg.get("range") + if not isinstance(cell_range, str): + raise ValueError("add_data_validation requires range") + data_validation = DataValidation( + type=cfg.get("validation_type"), + operator=cfg.get("operator"), + formula1=cfg.get("formula1"), + formula2=cfg.get("formula2"), + allow_blank=cfg.get("allow_blank"), + showInputMessage=cfg.get("show_input"), + showErrorMessage=cfg.get("show_error"), + promptTitle=cfg.get("prompt_title"), + prompt=cfg.get("prompt"), + errorTitle=cfg.get("error_title"), + error=cfg.get("error"), + ) + workbook[sheet].add_data_validation(data_validation) + data_validation.add(cell_range) def add_hyperlink(self, workbook: Any, sheet: str, link: JSONDict) -> None: - link_data = link.get("hyperlink", link) - cell = link_data.get("cell") - display = link_data.get("display") or link_data.get("target") - if isinstance(cell, str) and display is not None: - self.write_cell_value( - workbook, - sheet, - cell, - CellValue(type=CellType.STRING, value=str(display)), + from wolfxl.worksheet.hyperlink import Hyperlink + + cfg = link.get("hyperlink", link) + cell = cfg.get("cell") + if not isinstance(cell, str): + raise ValueError("add_hyperlink requires cell") + target = cfg.get("target") + current = workbook[sheet][cell] + if cfg.get("display") is not None: + current.value = cfg["display"] + if cfg.get("internal"): + current.hyperlink = Hyperlink( + ref=cell, location=str(target).lstrip("#") if target else None + ) + else: + current.hyperlink = Hyperlink( + ref=cell, target=str(target) if target else None ) - workbook.add_hyperlink(sheet, link_data) + if current.hyperlink is not None and cfg.get("tooltip") is not None: + current.hyperlink.tooltip = str(cfg["tooltip"]) def add_image(self, workbook: Any, sheet: str, image: JSONDict) -> None: - image_data = image.get("image", image) - path = image_data.get("path") - if not isinstance(path, str): - return - from wolfxl._images import image_to_writer_payload from wolfxl.drawing.image import Image - img = Image(path) - anchor = image_data.get("cell") or "A1" - img.anchor = str(anchor) - workbook.add_image(sheet, image_to_writer_payload(img)) + cfg = image.get("image", image) + path = cfg.get("path") + cell = cfg.get("cell") + if not isinstance(path, str) or not isinstance(cell, str): + raise ValueError("add_image requires path and cell") + workbook[sheet].add_image(Image(path), cell) def add_pivot_table(self, workbook: Any, sheet: str, pivot: JSONDict) -> None: - raise NotImplementedError("wolfxl pivot tables not implemented") + self.unsupported_operation( + "add_pivot_table", + ( + "WolfXL requires a concrete registered pivot cache; ExcelBench's " + "generic pivot payload cannot construct one." + ), + ) def add_comment(self, workbook: Any, sheet: str, comment: JSONDict) -> None: - workbook.add_comment(sheet, comment) + from wolfxl.comments import Comment + + cfg = comment.get("comment", comment) + cell = cfg.get("cell") + text = cfg.get("text") + if not isinstance(cell, str) or text is None: + raise ValueError("add_comment requires cell and text") + workbook[sheet][cell].comment = Comment(str(text), str(cfg.get("author") or "")) + + def add_named_range(self, workbook: Any, sheet: str, named_range: JSONDict) -> None: + from wolfxl.workbook.defined_name import DefinedName + + cfg = named_range.get("named_range", named_range) + name = cfg.get("name") + refers_to = cfg.get("refers_to") + if not isinstance(name, str) or not isinstance(refers_to, str): + raise ValueError("add_named_range requires name and refers_to") + defined_name = DefinedName( + name, attr_text=refers_to if refers_to.startswith("=") else f"={refers_to}" + ) + if cfg.get("scope", "workbook") == "sheet": + workbook[sheet].defined_names.add(defined_name) + else: + workbook.defined_names.add(defined_name) + + def add_table(self, workbook: Any, sheet: str, table: JSONDict) -> None: + from wolfxl.worksheet.filters import AutoFilter + from wolfxl.worksheet.table import Table, TableColumn, TableStyleInfo + + cfg = table.get("table", table) + name = cfg.get("name") + cell_range = cfg.get("ref") + if not isinstance(name, str) or not isinstance(cell_range, str): + raise ValueError("add_table requires name and ref") + result = Table(displayName=name, ref=cell_range) + if cfg.get("header_row") is False: + result.headerRowCount = 0 + if cfg.get("totals_row"): + result.totalsRowCount = 1 + if (style_name := cfg.get("style")) is not None: + result.tableStyleInfo = TableStyleInfo( + name=str(style_name), + showFirstColumn=False, + showLastColumn=False, + showRowStripes=True, + showColumnStripes=False, + ) + columns = cfg.get("columns") + if isinstance(columns, list) and columns: + result.tableColumns = [ + TableColumn(id=index, name=str(column)) + for index, column in enumerate(columns, start=1) + ] + if cfg.get("autofilter"): + result.autoFilter = AutoFilter(ref=cell_range) + workbook[sheet].add_table(result) def set_freeze_panes(self, workbook: Any, sheet: str, settings: JSONDict) -> None: - workbook.set_freeze_panes(sheet, settings) + cfg = settings.get("freeze", settings) + worksheet = workbook[sheet] + if cfg.get("mode") == "freeze": + worksheet.freeze_panes = cfg.get("top_left_cell") + return + if cfg.get("mode") == "split": + from wolfxl.worksheet.views import Pane + + worksheet.freeze_panes = None + pane = worksheet.sheet_view.pane or Pane() + worksheet.sheet_view.pane = pane + if cfg.get("x_split") is not None: + pane.xSplit = cfg["x_split"] + if cfg.get("y_split") is not None: + pane.ySplit = cfg["y_split"] + if cfg.get("top_left_cell") is not None: + pane.topLeftCell = cfg["top_left_cell"] + if cfg.get("active_pane") is not None: + pane.activePane = cfg["active_pane"] + pane.state = "split" + + # ========================================================================= + # Tier 4 operations + # ========================================================================= + + def read_sheet_protection(self, workbook: Any, sheet: str) -> JSONDict: + protection = workbook[sheet].protection + return { + "protected": bool(protection.sheet), + "password_hash_present": bool(protection.password or protection.hashValue), + "format_cells": protection.formatCells, + "insert_rows": protection.insertRows, + "select_locked_cells": protection.selectLockedCells, + "select_unlocked_cells": protection.selectUnlockedCells, + "sort": protection.sort, + "auto_filter": protection.autoFilter, + } + + def set_sheet_protection( + self, workbook: Any, sheet: str, settings: JSONDict + ) -> None: + cfg = settings.get("protection", settings) + protection = workbook[sheet].protection + for key, attr in ( + ("protected", "sheet"), + ("format_cells", "formatCells"), + ("insert_rows", "insertRows"), + ("select_locked_cells", "selectLockedCells"), + ("select_unlocked_cells", "selectUnlockedCells"), + ("sort", "sort"), + ("auto_filter", "autoFilter"), + ): + if cfg.get(key) is not None: + setattr(protection, attr, bool(cfg[key])) + if cfg.get("password"): + protection.set_password(str(cfg["password"])) + + def read_page_setup(self, workbook: Any, sheet: str) -> JSONDict: + worksheet = workbook[sheet] + page_setup = worksheet.page_setup + return { + "orientation": page_setup.orientation, + "fit_to_width": page_setup.fitToWidth, + "fit_to_height": page_setup.fitToHeight, + "scale": page_setup.scale, + "print_title_rows": worksheet.print_title_rows, + "header_center": worksheet.oddHeader.center.text, + "footer_center": worksheet.oddFooter.center.text, + } + + def set_page_setup(self, workbook: Any, sheet: str, settings: JSONDict) -> None: + cfg = settings.get("page_setup", settings) + worksheet = workbook[sheet] + page_setup = worksheet.page_setup + if cfg.get("orientation") is not None: + page_setup.orientation = str(cfg["orientation"]) + if cfg.get("fit_to_width") is not None: + page_setup.fitToWidth = int(cfg["fit_to_width"]) + if cfg.get("fit_to_height") is not None: + page_setup.fitToHeight = int(cfg["fit_to_height"]) + if cfg.get("scale") is not None: + page_setup.scale = int(cfg["scale"]) + if cfg.get("print_title_rows") is not None: + # WolfXL 2.1's public setter accepts the unanchored openpyxl + # compatibility spelling ("1:2"), while ExcelBench's contract + # uses the OOXML-style "$1:$2". + worksheet.print_title_rows = str(cfg["print_title_rows"]).replace("$", "") + if cfg.get("header_center") is not None: + worksheet.oddHeader.center.text = str(cfg["header_center"]) + if cfg.get("footer_center") is not None: + worksheet.oddFooter.center.text = str(cfg["footer_center"]) + + def read_chart_anchors(self, workbook: Any, sheet: str) -> list[JSONDict]: + def cell_from_marker(marker: Any) -> str | None: + if marker is None: + return None + return f"{_col_letter(marker.col + 1)}{marker.row + 1}" + + charts = getattr(workbook[sheet], "_charts", None) + if charts is None: + self.unsupported_operation( + "read_chart_anchors", + "WolfXL's installed compatibility layer does not expose charts.", + ) + results: list[JSONDict] = [] + for chart in charts: + anchor = getattr(chart, "anchor", None) + # In WolfXL 2.1 a loaded chart's public anchor is its default + # placement cell, while the persisted DrawingML anchor is retained + # in the openpyxl-compatible private _anchor field. + if isinstance(anchor, str): + anchor = getattr(chart, "_anchor", None) + anchor_name = type(anchor).__name__ if anchor is not None else "" + results.append( + { + "type": type(chart).__name__.replace("Chart", "").lower() or None, + "anchor_type": ( + "twoCell" + if anchor_name == "TwoCellAnchor" + else "oneCell" + if anchor_name == "OneCellAnchor" + else "absolute" + if anchor_name == "AbsoluteAnchor" + else None + ), + "from": cell_from_marker(getattr(anchor, "_from", None)), + "to": cell_from_marker(getattr(anchor, "to", None)) + if anchor_name == "TwoCellAnchor" + else None, + } + ) + return results + + def add_chart_with_anchor(self, workbook: Any, sheet: str, chart: JSONDict) -> None: + from wolfxl.chart import BarChart, LineChart, Reference + from wolfxl.drawing.spreadsheet_drawing import AnchorMarker, TwoCellAnchor + from wolfxl.utils.cell import coordinate_to_tuple + + cfg = chart.get("chart", chart) + data_ref = cfg.get("data_ref") + if not isinstance(data_ref, str) or not data_ref: + raise ValueError("add_chart_with_anchor requires data_ref") + worksheet = workbook[sheet] + series_chart: Any = ( + LineChart() if str(cfg.get("type", "bar")).lower() == "line" else BarChart() + ) + qualified_data_ref = ( + data_ref if "!" in data_ref else f"{worksheet.title}!{data_ref}" + ) + series_chart.add_data( + Reference(worksheet, range_string=qualified_data_ref), + titles_from_data=False, + ) + if (categories_ref := cfg.get("categories_ref")) is not None: + categories = str(categories_ref) + qualified_categories = ( + categories if "!" in categories else f"{worksheet.title}!{categories}" + ) + series_chart.set_categories( + Reference(worksheet, range_string=qualified_categories) + ) + from_row, from_column = coordinate_to_tuple(str(cfg.get("from") or "B2")) + to_row, to_column = coordinate_to_tuple(str(cfg.get("to") or "H12")) + series_chart.anchor = TwoCellAnchor( + _from=AnchorMarker(col=from_column - 1, row=from_row - 1), + to=AnchorMarker(col=to_column - 1, row=to_row - 1), + ) + worksheet.add_chart(series_chart) def save_workbook(self, workbook: Any, path: Path) -> None: - workbook.save(str(path)) + workbook.save(path) diff --git a/src/excelbench/harness/adapters/zavora_adapter.py b/src/excelbench/harness/adapters/zavora_adapter.py new file mode 100644 index 0000000..6bc6656 --- /dev/null +++ b/src/excelbench/harness/adapters/zavora_adapter.py @@ -0,0 +1,331 @@ +"""Write-oriented adapter backed by the Zavora external helper.""" + +from __future__ import annotations + +from dataclasses import asdict +from pathlib import Path +from typing import Any + +from excelbench.harness.adapters.base import WriteOnlyAdapter +from excelbench.harness.external_oracles import ( + ExternalOracleRequest, + ExternalOracleTool, + external_oracle_catalog, + run_external_oracle, +) +from excelbench.models import BorderInfo, CellFormat, CellType, CellValue, LibraryInfo + +WorkbookData = dict[str, Any] + + +class ZavoraAdapter(WriteOnlyAdapter): + """Cross-language write-first adapter backed by the Zavora Rust helper.""" + + @classmethod + def repo_root(cls) -> Path: + return Path(__file__).resolve().parents[4] + + @classmethod + def tool(cls) -> ExternalOracleTool: + return external_oracle_catalog(repo_root=cls.repo_root())["zavora"] + + @classmethod + def is_available(cls) -> bool: + return cls.tool().is_available() + + @property + def info(self) -> LibraryInfo: + return LibraryInfo( + name="zavora-xlsx", + version="0.1.2", + language="rust", + capabilities={"write"}, + ) + + def create_workbook(self) -> WorkbookData: + return { + "sheets": [], + "cells": [], + "formats": [], + "borders": [], + "columns": [], + "row_heights": [], + "merges": [], + "validations": [], + "hyperlinks": [], + "comments": [], + "panes": [], + "named_ranges": [], + "tables": [], + "conditional_formats": [], + "charts": [], + "pivots": [], + "slicers": [], + "pictures": [], + } + + def add_sheet(self, workbook: WorkbookData, name: str) -> None: + if not any(sheet["name"] == name for sheet in workbook["sheets"]): + workbook["sheets"].append({"name": name}) + + def _ensure_sheet(self, workbook: WorkbookData, sheet: str) -> None: + self.add_sheet(workbook, sheet) + + def write_cell_value( + self, + workbook: WorkbookData, + sheet: str, + cell: str, + value: CellValue, + ) -> None: + self._ensure_sheet(workbook, sheet) + entry: dict[str, Any] = {"sheet": sheet, "cell": cell} + if value.type == CellType.FORMULA: + entry["type"] = "formula" + entry["formula"] = value.formula or str(value.value or "") + entry["value"] = value.value + elif value.type == CellType.BLANK or ( + value.type == CellType.STRING and value.value == "" + ): + entry["type"] = "blank" + entry["value"] = None + else: + entry["type"] = str(value.type) + entry["value"] = self._serialize_value(value) + workbook["cells"].append(entry) + + def write_cell_format( + self, + workbook: WorkbookData, + sheet: str, + cell: str, + format: CellFormat, + ) -> None: + self._ensure_sheet(workbook, sheet) + workbook["formats"].append( + { + "sheet": sheet, + "cell": cell, + "bold": format.bold, + "italic": format.italic, + "underline": format.underline, + "strikethrough": format.strikethrough, + "font_name": format.font_name, + "font_size": format.font_size, + "font_color": format.font_color, + "bg_color": format.bg_color, + "number_format": format.number_format, + "h_align": format.h_align, + "v_align": format.v_align, + "wrap": format.wrap, + "rotation": format.rotation, + "indent": format.indent, + } + ) + + def write_cell_border( + self, + workbook: WorkbookData, + sheet: str, + cell: str, + border: BorderInfo, + ) -> None: + self._ensure_sheet(workbook, sheet) + workbook["borders"].append( + {"sheet": sheet, "cell": cell, "border": asdict(border)} + ) + + def set_row_height( + self, + workbook: WorkbookData, + sheet: str, + row: int, + height: float, + ) -> None: + self._ensure_sheet(workbook, sheet) + workbook["row_heights"].append({"sheet": sheet, "row": row, "height": height}) + + def set_column_width( + self, + workbook: WorkbookData, + sheet: str, + column: str, + width: float, + ) -> None: + self._ensure_sheet(workbook, sheet) + workbook["columns"].append( + {"sheet": sheet, "start": column, "end": column, "width": width} + ) + + def merge_cells(self, workbook: WorkbookData, sheet: str, cell_range: str) -> None: + self._ensure_sheet(workbook, sheet) + workbook["merges"].append({"sheet": sheet, "range": cell_range}) + + def add_conditional_format( + self, workbook: WorkbookData, sheet: str, rule: dict[str, Any] + ) -> None: + self._ensure_sheet(workbook, sheet) + payload = rule.get("cf_rule", rule) + workbook["conditional_formats"].append( + { + "sheet": sheet, + "range": payload.get("range"), + "type": self._map_conditional_format_type(payload.get("rule_type")), + "criteria": self._map_conditional_format_criteria( + payload.get("rule_type"), + payload.get("operator"), + payload.get("formula"), + ), + "value": self._map_conditional_format_value(payload), + "stop_if_true": payload.get("stop_if_true", False), + "bg_color": (payload.get("format") or {}).get("bg_color", ""), + } + ) + + def add_data_validation( + self, workbook: WorkbookData, sheet: str, validation: dict[str, Any] + ) -> None: + self._ensure_sheet(workbook, sheet) + payload = validation.get("validation", validation) + workbook["validations"].append({"sheet": sheet, **payload}) + + def add_hyperlink( + self, workbook: WorkbookData, sheet: str, link: dict[str, Any] + ) -> None: + self._ensure_sheet(workbook, sheet) + payload = link.get("hyperlink", link) + workbook["hyperlinks"].append({"sheet": sheet, **payload}) + + def add_image( + self, workbook: WorkbookData, sheet: str, image: dict[str, Any] + ) -> None: + self._ensure_sheet(workbook, sheet) + payload = image.get("image", image) + workbook["pictures"].append({"sheet": sheet, **payload}) + + def add_pivot_table( + self, workbook: WorkbookData, sheet: str, pivot: dict[str, Any] + ) -> None: + payload = pivot.get("pivot", pivot) + target_cell = payload.get("target_cell") + target_range = payload.get("range") + if target_range is None and target_cell is not None: + target_range = f"{sheet}!{target_cell}:{target_cell}" + workbook["pivots"].append( + { + "data_range": payload.get("source_range") or payload.get("data_range"), + "range": target_range, + "name": payload.get("name"), + "rows": payload.get("rows") + or [{"name": name} for name in payload.get("row_fields", [])], + "columns": payload.get("columns") + or [{"name": name} for name in payload.get("column_fields", [])], + "data": payload.get("data") + or [ + {"name": name, "subtotal": "Sum"} + for name in payload.get("data_fields", []) + ], + "filters": payload.get("filters") + or [{"name": name} for name in payload.get("filter_fields", [])], + } + ) + + def add_comment( + self, workbook: WorkbookData, sheet: str, comment: dict[str, Any] + ) -> None: + self._ensure_sheet(workbook, sheet) + payload = comment.get("comment", comment) + workbook["comments"].append({"sheet": sheet, **payload}) + + def set_freeze_panes( + self, workbook: WorkbookData, sheet: str, settings: dict[str, Any] + ) -> None: + self._ensure_sheet(workbook, sheet) + payload = settings.get("freeze", settings) + workbook["panes"].append({"sheet": sheet, **payload}) + + def add_table( + self, workbook: WorkbookData, sheet: str, table: dict[str, Any] + ) -> None: + self._ensure_sheet(workbook, sheet) + payload = table.get("table", table) + workbook["tables"].append( + { + "sheet": sheet, + "range": payload.get("ref") or payload.get("range"), + "name": payload.get("name"), + "style": payload.get("style"), + "show_header_row": payload.get("header_row", True), + "show_row_stripes": True, + "totals_row": payload.get("totals_row", False), + "columns": payload.get("columns", []), + "autofilter": payload.get("autofilter", False), + } + ) + + def add_named_range( + self, workbook: WorkbookData, sheet: str, named_range: dict[str, Any] + ) -> None: + self._ensure_sheet(workbook, sheet) + payload = named_range.get("named_range", named_range) + workbook["named_ranges"].append({"sheet": sheet, **payload}) + + def save_workbook(self, workbook: WorkbookData, path: Path) -> None: + result = run_external_oracle( + self.tool(), + ExternalOracleRequest( + fixture_id="zavora-adapter", + operation="write_fixture", + output_path=path, + payload=workbook, + ), + timeout_seconds=300, + ) + if result.skipped: + raise FileNotFoundError(result.notes or "Zavora helper unavailable") + if not result.passed: + message = result.payload.get("message") or result.stderr or result.stdout + raise RuntimeError(str(message)) + + def _serialize_value(self, value: CellValue) -> Any: + if value.type == CellType.BLANK: + return None + if value.type == CellType.DATE and value.value is not None: + return value.value.isoformat() + if value.type == CellType.DATETIME and value.value is not None: + return value.value.isoformat(timespec="seconds") + return value.value + + def _map_conditional_format_type(self, value: Any) -> str: + rule_type = str(value or "") + if rule_type == "colorScale": + return "3_color_scale" + if rule_type == "dataBar": + return "data_bar" + if rule_type == "iconSet": + return "icon_set" + if rule_type == "expression": + return "formula" + return "cell" + + def _map_conditional_format_criteria( + self, rule_type: Any, operator: Any, formula: Any + ) -> str: + if str(rule_type or "") == "expression": + return str(formula or "").lstrip("=") + mapping = { + "greaterThan": ">", + "greaterThanOrEqual": ">=", + "lessThan": "<", + "lessThanOrEqual": "<=", + "equal": "==", + "notEqual": "!=", + "between": "between", + "notBetween": "not between", + } + return mapping.get(str(operator or ""), ">") + + def _map_conditional_format_value(self, payload: dict[str, Any]) -> str: + if str(payload.get("rule_type") or "") == "expression": + return "" + return (payload.get("formula") or payload.get("value") or "0").lstrip("=") diff --git a/src/excelbench/harness/calc.py b/src/excelbench/harness/calc.py new file mode 100644 index 0000000..6992f8b --- /dev/null +++ b/src/excelbench/harness/calc.py @@ -0,0 +1,439 @@ +"""Formula recalculation engines and oracle-backed comparison for ExcelBench.""" + +from __future__ import annotations + +import json +import math +import shutil +import subprocess +import tempfile +from collections.abc import Mapping +from pathlib import Path +from typing import Any, Protocol + +from openpyxl import load_workbook + +from excelbench.harness.external_oracles import ( + ExternalOracleRequest, + external_oracle_catalog, + run_external_oracle, +) +from excelbench.results.calc_renderer import render_calc_results + +SOFFICE_PATH = Path("/opt/homebrew/bin/soffice") + + +class CalcEngine(Protocol): + """Protocol implemented by a spreadsheet formula recalculation engine.""" + + name: str + + def available(self) -> bool: + """Return whether this engine can run on the current machine.""" + + def calculate(self, input_path: Path, output_path: Path) -> dict[str, Any]: + """Calculate a workbook and return its formula-cell values.""" + + +def formula_cells(input_path: Path) -> list[str]: + """Return workbook-qualified references for every formula cell in a workbook.""" + workbook = load_workbook(input_path, data_only=False, read_only=True) + try: + return [ + f"{worksheet.title}!{cell.coordinate}" + for worksheet in workbook.worksheets + for row in worksheet.iter_rows() + for cell in row + if isinstance(cell.value, str) and cell.value.startswith("=") + ] + finally: + workbook.close() + + +def libreoffice_version() -> str | None: + """Return LibreOffice's version string when the configured binary is present.""" + if not SOFFICE_PATH.is_file(): + return None + completed = subprocess.run( + [str(SOFFICE_PATH), "--version"], + capture_output=True, + check=False, + text=True, + timeout=30, + ) + if completed.returncode != 0: + return None + version = completed.stdout.strip() or completed.stderr.strip() + return version or None + + +def recalculate_with_libreoffice(input_path: Path, output_path: Path) -> str | None: + """Recalculate ``input_path`` through an isolated headless LibreOffice profile. + + The workbook is copied to a temporary source directory before ``--convert-to + xlsx`` runs, so LibreOffice always writes a distinct file and its calculated + cell caches can be copied to ``output_path`` safely. + """ + if not SOFFICE_PATH.is_file(): + return f"LibreOffice binary not found at {SOFFICE_PATH}" + + output_path.parent.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory(prefix="excelbench-libreoffice-") as temporary_dir: + work_dir = Path(temporary_dir) + source_dir = work_dir / "source" + converted_dir = work_dir / "converted" + profile_dir = work_dir / "profile" + source_dir.mkdir() + converted_dir.mkdir() + profile_dir.mkdir() + source_path = source_dir / input_path.name + shutil.copy2(input_path, source_path) + command = [ + str(SOFFICE_PATH), + "--headless", + f"-env:UserInstallation={profile_dir.as_uri()}", + "--convert-to", + "xlsx", + "--outdir", + str(converted_dir), + str(source_path), + ] + try: + completed = subprocess.run( + command, + cwd=work_dir, + capture_output=True, + check=False, + text=True, + timeout=120, + ) + except (OSError, subprocess.TimeoutExpired) as exc: + return f"LibreOffice conversion could not run: {exc}" + if completed.returncode != 0: + detail = (completed.stderr or completed.stdout).strip() or "no diagnostic" + return f"LibreOffice conversion failed: {detail}" + + converted_path = converted_dir / input_path.name + if not converted_path.is_file(): + detail = ( + completed.stderr or completed.stdout + ).strip() or "no output workbook" + return f"LibreOffice conversion produced no XLSX: {detail}" + shutil.copy2(converted_path, output_path) + return None + + +def _read_values( + workbook_path: Path, references: list[str], *, reader: str +) -> dict[str, Any]: + if reader == "wolfxl": + import wolfxl + + workbook = wolfxl.load_workbook(workbook_path, data_only=True) + return { + reference: workbook[sheet_name][cell_reference].value + for reference in references + for sheet_name, cell_reference in [reference.split("!", maxsplit=1)] + } + + workbook = load_workbook(workbook_path, data_only=True, read_only=True) + try: + return { + reference: workbook[sheet_name][cell_reference].value + for reference in references + for sheet_name, cell_reference in [reference.split("!", maxsplit=1)] + } + finally: + workbook.close() + + +class WolfXLCalcEngine: + """Formula calculation through WolfXL's public workbook API.""" + + name = "wolfxl" + + def available(self) -> bool: + """Return whether WolfXL can be imported.""" + try: + import wolfxl # noqa: F401 + except ImportError: + return False + return True + + def calculate(self, input_path: Path, output_path: Path) -> dict[str, Any]: + """Calculate with WolfXL, save the workbook, and read cached results.""" + try: + import wolfxl + + output_path.parent.mkdir(parents=True, exist_ok=True) + references = formula_cells(input_path) + workbook = wolfxl.load_workbook(input_path) + workbook.calculate() + workbook.save(output_path) + return { + "status": "passed", + "values": _read_values(output_path, references, reader="wolfxl"), + "reason": None, + } + except Exception as exc: # Engine errors are data for the comparison report. + return { + "status": "failed", + "values": {}, + "reason": f"{type(exc).__name__}: {exc}", + } + + +class LibreOfficeCalcEngine: + """Formula calculation through headless LibreOffice conversion.""" + + name = "libreoffice" + + def available(self) -> bool: + """Return whether the configured LibreOffice binary is available.""" + return libreoffice_version() is not None + + def calculate(self, input_path: Path, output_path: Path) -> dict[str, Any]: + """Calculate with LibreOffice and read cached results from its output.""" + reason = recalculate_with_libreoffice(input_path, output_path) + if reason is not None: + return {"status": "failed", "values": {}, "reason": reason} + try: + return { + "status": "passed", + "values": _read_values( + output_path, formula_cells(input_path), reader="openpyxl" + ), + "reason": None, + } + except Exception as exc: # Engine errors are data for the comparison report. + return { + "status": "failed", + "values": {}, + "reason": f"{type(exc).__name__}: {exc}", + } + + +class AsposeCellsFossCalcEngine: + """Best-effort evaluation through the intentionally limited FOSS evaluator.""" + + name = "aspose_cells_foss" + + def available(self) -> bool: + """Return whether Aspose.Cells FOSS can be imported.""" + try: + import aspose.cells_foss # noqa: F401 + from aspose.cells_foss.formula_evaluator import FormulaEvaluator # noqa: F401 + except ImportError: + return False + return True + + def calculate(self, input_path: Path, output_path: Path) -> dict[str, Any]: + """Evaluate every formula with the FOSS evaluator and save its output.""" + try: + from aspose.cells_foss import Workbook + from aspose.cells_foss.formula_evaluator import FormulaEvaluator + + workbook = Workbook(str(input_path)) + evaluator = FormulaEvaluator(workbook) + values: dict[str, Any] = {} + unsupported: list[str] = [] + for worksheet in workbook.worksheets: + for cell_reference, cell in worksheet.cells: + if not isinstance(cell.formula, str) or not cell.formula.startswith( + "=" + ): + continue + value = evaluator.evaluate(cell.formula, worksheet, cell_reference) + reference = f"{worksheet.name}!{cell_reference}" + values[reference] = value + if value is None: + unsupported.append(reference) + output_path.parent.mkdir(parents=True, exist_ok=True) + workbook.save(str(output_path)) + if unsupported: + preview = ", ".join(unsupported[:5]) + return { + "status": "failed", + "values": values, + "reason": ( + "FOSS FormulaEvaluator returned no value for " + f"{len(unsupported)} formulas: {preview}" + ), + } + return {"status": "passed", "values": values, "reason": None} + except Exception as exc: # Its unsupported parser must not escape the suite. + return { + "status": "failed", + "values": {}, + "reason": f"{type(exc).__name__}: {exc}", + } + + +class ZavoraCalcEngine: + """Formula calculation through the optional Zavora external oracle helper.""" + + name = "zavora" + + def available(self) -> bool: + """Return whether the catalogued Zavora helper can be launched.""" + return external_oracle_catalog(_repository_root())["zavora"].is_available() + + def calculate(self, input_path: Path, output_path: Path) -> dict[str, Any]: + """Delegate calculation to Zavora's JSON external-oracle protocol.""" + tool = external_oracle_catalog(_repository_root())["zavora"] + if not tool.is_available(): + return { + "status": "unavailable", + "values": {}, + "reason": "Zavora helper is unavailable", + } + result = run_external_oracle( + tool, + ExternalOracleRequest( + fixture_id=input_path.stem, + operation="calculate", + payload={}, + input_path=input_path.resolve(), + output_path=output_path.resolve(), + ), + ) + if result.skipped: + return { + "status": "unavailable", + "values": {}, + "reason": result.notes or "Zavora helper skipped", + } + if not result.passed: + detail = ( + result.notes + or result.stderr.strip() + or result.stdout.strip() + or "no diagnostic" + ) + return { + "status": "failed", + "values": {}, + "reason": f"Zavora calculation failed: {detail}", + } + values = result.payload.get("values") + if not isinstance(values, dict): + return { + "status": "failed", + "values": {}, + "reason": "Zavora response omitted values", + } + return {"status": "passed", "values": values, "reason": None} + + +def values_match(expected: Any, actual: Any) -> bool: + """Compare calculation values with number tolerance and exact scalar semantics.""" + if isinstance(expected, bool) or isinstance(actual, bool): + return ( + isinstance(expected, bool) + and isinstance(actual, bool) + and expected is actual + ) + if isinstance(expected, (int, float)) and isinstance(actual, (int, float)): + return math.isclose(float(expected), float(actual), abs_tol=1e-6, rel_tol=1e-9) + return expected == actual + + +def run_calc_suite( + fixture: Path, expected: dict[str, Any] | Path, output_dir: Path +) -> dict[str, Any]: + """Run available engines against the LibreOffice calculation oracle fixture.""" + expected_data = _load_expected(expected) + expected_cells = expected_data["cells"] + if not isinstance(expected_cells, Mapping): + raise ValueError("Expected calculation data must contain a cells mapping") + + output_dir.mkdir(parents=True, exist_ok=True) + engine_results: dict[str, dict[str, Any]] = {} + for engine in _engines(): + if not engine.available(): + engine_results[engine.name] = { + "status": "unavailable", + "matched": 0, + "total": len(expected_cells), + "mismatched_cells": [], + "reason": f"{engine.name} is unavailable", + } + continue + engine_result = engine.calculate( + fixture, output_dir / engine.name / fixture.name + ) + values = engine_result.get("values", {}) + if not isinstance(values, Mapping): + values = {} + matched, mismatches = _compare_expected_values(expected_cells, values) + total = len(expected_cells) + if engine_result["status"] == "passed" and matched < total: + # An engine that runs but produces wrong or missing values is a + # failed calculation run, not a pass. + status = "failed" + missing = sum(1 for m in mismatches if m.get("actual") is None) + wrong = len(mismatches) - missing + reason = ( + f"{total - matched}/{total} formula values wrong or missing " + f"(first mismatch batch: {len(mismatches)} shown, " + f"{missing} missing, {wrong} wrong)" + ) + else: + status = engine_result["status"] + reason = engine_result.get("reason") + engine_results[engine.name] = { + "status": status, + "matched": matched, + "total": total, + "mismatched_cells": mismatches, + "reason": reason, + } + + results = { + "fixture": str(fixture), + "oracle": expected_data.get("oracle"), + "engines": engine_results, + } + render_calc_results(results, output_dir) + return results + + +def _compare_expected_values( + expected_cells: Mapping[str, Any], actual_values: Mapping[str, Any] +) -> tuple[int, list[dict[str, Any]]]: + matched = 0 + mismatches: list[dict[str, Any]] = [] + for reference, expected_cell in expected_cells.items(): + if not isinstance(expected_cell, Mapping) or "value" not in expected_cell: + raise ValueError(f"Expected cell {reference} has no value") + expected_value = expected_cell["value"] + actual_value = actual_values.get(reference) + if values_match(expected_value, actual_value): + matched += 1 + elif len(mismatches) < 10: + mismatches.append( + {"cell": reference, "expected": expected_value, "actual": actual_value} + ) + return matched, mismatches + + +def _engines() -> tuple[CalcEngine, ...]: + return ( + WolfXLCalcEngine(), + LibreOfficeCalcEngine(), + AsposeCellsFossCalcEngine(), + ZavoraCalcEngine(), + ) + + +def _load_expected(expected: dict[str, Any] | Path) -> dict[str, Any]: + if isinstance(expected, Path): + expected_path = ( + expected / "expected_values.json" if expected.is_dir() else expected + ) + return json.loads(expected_path.read_text()) + return expected + + +def _repository_root() -> Path: + return Path(__file__).resolve().parents[3] diff --git a/src/excelbench/harness/external_oracles.py b/src/excelbench/harness/external_oracles.py index 54d9dd3..6f7d535 100644 --- a/src/excelbench/harness/external_oracles.py +++ b/src/excelbench/harness/external_oracles.py @@ -117,7 +117,9 @@ class ExternalOracleResult: notes: str | None = None -def external_oracle_catalog(repo_root: Path | None = None) -> dict[str, ExternalOracleTool]: +def external_oracle_catalog( + repo_root: Path | None = None, +) -> dict[str, ExternalOracleTool]: """Return the planned external-oracle helper catalog. The commands are helper entrypoints, not raw runtime commands. They are @@ -133,7 +135,13 @@ def external_oracle_catalog(repo_root: Path | None = None) -> dict[str, External if repo_root is not None: libreoffice_command = ( sys.executable, - str(repo_root / "tools" / "external-oracles" / "libreoffice" / "libreoffice_oracle.py"), + str( + repo_root + / "tools" + / "external-oracles" + / "libreoffice" + / "libreoffice_oracle.py" + ), ) closedxml_command: tuple[str, ...] = ("excelbench-closedxml-oracle",) if repo_root is not None: @@ -141,7 +149,13 @@ def external_oracle_catalog(repo_root: Path | None = None) -> dict[str, External "dotnet", "run", "--project", - str(repo_root / "tools" / "external-oracles" / "closedxml" / "closedxml-oracle.csproj"), + str( + repo_root + / "tools" + / "external-oracles" + / "closedxml" + / "closedxml-oracle.csproj" + ), "--configuration", "Release", "--no-launch-profile", @@ -155,7 +169,9 @@ def external_oracle_catalog(repo_root: Path | None = None) -> dict[str, External "dotnet", "run", "--project", - str(repo_root / "tools" / "external-oracles" / "npoi" / "npoi-oracle.csproj"), + str( + repo_root / "tools" / "external-oracles" / "npoi" / "npoi-oracle.csproj" + ), "--configuration", "Release", "--no-launch-profile", @@ -169,7 +185,9 @@ def external_oracle_catalog(repo_root: Path | None = None) -> dict[str, External if repo_root is not None: exceljs_cwd = repo_root / "tools" / "external-oracles" / "exceljs" exceljs_command = ("node", str(exceljs_cwd / "exceljs-oracle.cjs")) - exceljs_required_paths = (exceljs_cwd / "node_modules" / "exceljs" / "package.json",) + exceljs_required_paths = ( + exceljs_cwd / "node_modules" / "exceljs" / "package.json", + ) apache_poi_command: tuple[str, ...] = ("excelbench-poi-oracle",) apache_poi_cwd = None apache_poi_required_paths: tuple[Path, ...] = () @@ -184,6 +202,14 @@ def external_oracle_catalog(repo_root: Path | None = None) -> dict[str, External apache_poi_cwd / "deps" / "lib" / "poi-ooxml-5.5.1.jar", ) + zavora_command: tuple[str, ...] = ("excelbench-zavora-oracle",) + zavora_cwd = None + zavora_required_paths: tuple[Path, ...] = () + if repo_root is not None: + zavora_cwd = repo_root / "tools" / "external-oracles" / "zavora" + zavora_command = ("cargo", "run", "--quiet") + zavora_required_paths = (zavora_cwd / "Cargo.toml",) + return { "excelize": ExternalOracleTool( name="excelize", @@ -243,14 +269,27 @@ def external_oracle_catalog(repo_root: Path | None = None) -> dict[str, External command=closedxml_command, language="dotnet", homepage="https://docs.closedxml.io/", - capabilities=frozenset({"read", "write", "pivots", "conditional_formatting"}), + capabilities=frozenset( + {"read", "write", "pivots", "conditional_formatting"} + ), ), "npoi": ExternalOracleTool( name="npoi", command=npoi_command, language="dotnet", homepage="https://github.com/nissl-lab/npoi", - capabilities=frozenset({"read", "write", "comments", "rich_text", "protection"}), + capabilities=frozenset( + {"read", "write", "comments", "rich_text", "protection"} + ), + ), + "zavora": ExternalOracleTool( + name="zavora", + command=zavora_command, + language="rust", + homepage="https://github.com/zavora-ai/zavora-xlsx", + capabilities=frozenset({"read", "write", "mutate", "calculate"}), + cwd=zavora_cwd, + required_paths=zavora_required_paths, ), } diff --git a/src/excelbench/harness/mutation.py b/src/excelbench/harness/mutation.py new file mode 100644 index 0000000..7f65826 --- /dev/null +++ b/src/excelbench/harness/mutation.py @@ -0,0 +1,364 @@ +"""Isolated mutation timing and OOXML preservation scoring.""" + +from __future__ import annotations + +import hashlib +import json +import os +import posixpath +import re +import shutil +import statistics +import subprocess +import sys +import time +import xml.etree.ElementTree as ET +from pathlib import Path, PurePosixPath +from typing import Any +from zipfile import ZipFile + +import openpyxl + +from excelbench.modifiable import ModifiableEngine, Mutation, modifiable_engines + +_WORKSHEET_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main" +_RELATIONSHIPS_NS = "http://schemas.openxmlformats.org/package/2006/relationships" +_CONTENT_TYPES_NS = "http://schemas.openxmlformats.org/package/2006/content-types" +_DRIVER = """ +import json +import sys +from pathlib import Path +from excelbench.modifiable import modifiable_engines + +name, template, output, mutations = sys.argv[1:] +engine = next(item for item in modifiable_engines() if item.name == name) +engine.mutate(Path(template), Path(output), json.loads(mutations)) +""" +_ELAPSED_RE = re.compile(r"^\s*(?P\d+(?:\.\d+)?)\s+real\b", re.MULTILINE) +_RSS_RE = re.compile(r"^\s*(?P\d+)\s+maximum resident set size\b", re.MULTILINE) +_ELEMENT_CHECKS = ( + "tableParts", + "sheetProtection", + "dataValidations", + "conditionalFormatting", + "pageSetup", + "headerFooter", + "sheetPr", + "pane", + "drawing", +) + + +def _sha256_file(path: Path) -> str: + """Return a SHA-256 digest for a complete file.""" + digest = hashlib.sha256() + with path.open("rb") as source: + for chunk in iter(lambda: source.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def _package_parts(path: Path) -> dict[str, bytes]: + """Read all file parts from an OOXML zip package.""" + with ZipFile(path) as archive: + return { + name: archive.read(name) + for name in archive.namelist() + if not name.endswith("/") + } + + +def _xml_has_element(xml: bytes, element: str) -> bool: + """Return whether a worksheet XML part contains the given main-namespace element.""" + try: + root = ET.fromstring(xml) + except ET.ParseError: + return False + return root.find(f".//{{{_WORKSHEET_NS}}}{element}") is not None + + +def _element_checklist( + original_parts: dict[str, bytes], output_parts: dict[str, bytes] +) -> list[dict[str, Any]]: + """Compare preservation-relevant worksheet elements part by part.""" + checks: list[dict[str, Any]] = [] + for part_name in sorted( + name + for name in original_parts + if name.startswith("xl/worksheets/") and name.endswith(".xml") + ): + original_xml = original_parts[part_name] + output_xml = output_parts.get(part_name, b"") + for element in _ELEMENT_CHECKS: + present_in_original = _xml_has_element(original_xml, element) + present_in_output = _xml_has_element(output_xml, element) + checks.append( + { + "part": part_name, + "element": element, + "present_in_original": present_in_original, + "present_in_output": present_in_output, + } + ) + return checks + + +def _relationship_target(rel_part: str, target: str) -> str: + """Resolve an internal relationship target to its package part name.""" + if target.startswith("/"): + return target.removeprefix("/") + rel_path = PurePosixPath(rel_part) + owner_directory = rel_path.parent.parent + return posixpath.normpath(posixpath.join(str(owner_directory), target)) + + +def _dangling_relationships(parts: dict[str, bytes]) -> list[str]: + """Return unresolved internal relationship targets declared under ``xl/``.""" + dangling: list[str] = [] + relationship_tag = f"{{{_RELATIONSHIPS_NS}}}Relationship" + for rel_part, xml in sorted(parts.items()): + if not rel_part.startswith("xl/") or not rel_part.endswith(".rels"): + continue + try: + root = ET.fromstring(xml) + except ET.ParseError: + dangling.append(f"{rel_part}: invalid relationship XML") + continue + for relationship in root.findall(relationship_tag): + if relationship.get("TargetMode") == "External": + continue + target = relationship.get("Target") + if not target: + dangling.append(f"{rel_part}: missing target") + continue + resolved = _relationship_target(rel_part, target) + if resolved.startswith("xl/") and resolved not in parts: + dangling.append(f"{rel_part}: {resolved}") + return dangling + + +def _missing_content_types(parts: dict[str, bytes]) -> list[str]: + """Return package parts lacking an OOXML content-type declaration.""" + content_types = parts.get("[Content_Types].xml") + if content_types is None: + return ["[Content_Types].xml"] + try: + root = ET.fromstring(content_types) + except ET.ParseError: + return ["[Content_Types].xml"] + default_tag = f"{{{_CONTENT_TYPES_NS}}}Default" + override_tag = f"{{{_CONTENT_TYPES_NS}}}Override" + defaults = {item.get("Extension") for item in root.findall(default_tag)} + overrides = { + item.get("PartName", "").removeprefix("/") + for item in root.findall(override_tag) + } + missing: list[str] = [] + for part_name in sorted(parts): + if part_name == "[Content_Types].xml": + continue + extension = part_name.rsplit(".", 1)[-1] if "." in part_name else "" + if part_name not in overrides and extension not in defaults: + missing.append(part_name) + return missing + + +def score_preservation(template: Path, output: Path) -> dict[str, Any]: + """Score a mutation output against its original OOXML package structure.""" + original_parts = _package_parts(template) + output_parts = _package_parts(output) + original_names = set(original_parts) + output_names = set(output_parts) + lost_parts = sorted(original_names - output_names) + added_parts = sorted(output_names - original_names) + + checklist = _element_checklist(original_parts, output_parts) + expected_checks = [entry for entry in checklist if entry["present_in_original"]] + retained_checks = [entry for entry in expected_checks if entry["present_in_output"]] + element_score = 30.0 + if expected_checks: + element_score *= len(retained_checks) / len(expected_checks) + + dangling_rels = _dangling_relationships(output_parts) + missing_content_types = _missing_content_types(output_parts) + integrity_issue_count = len(dangling_rels) + len(missing_content_types) + integrity_score = max(0.0, 20.0 - 5.0 * integrity_issue_count) + + custom_parts = sorted( + name for name in original_parts if name.startswith("customXml/") + ) + custom_xml_identical = all( + name in output_parts + and hashlib.sha256(original_parts[name]).digest() + == hashlib.sha256(output_parts[name]).digest() + for name in custom_parts + ) + custom_xml_score = 10.0 if custom_xml_identical else 0.0 + parts_score = max(0.0, 40.0 - 10.0 * len(lost_parts)) + preservation_score = round( + parts_score + element_score + integrity_score + custom_xml_score, 2 + ) + + return { + "preservation_score": preservation_score, + "details": { + "lost_parts": lost_parts, + "added_parts": added_parts, + "element_diffs": checklist, + "dangling_rels": dangling_rels, + "missing_content_types": missing_content_types, + "customXml_identical": custom_xml_identical, + }, + } + + +def _parse_time_output(stderr: str) -> tuple[float | None, float | None]: + """Extract macOS ``time -l`` elapsed seconds and RSS kilobytes.""" + elapsed_match = _ELAPSED_RE.search(stderr) + rss_match = _RSS_RE.search(stderr) + elapsed_seconds = float(elapsed_match.group("seconds")) if elapsed_match else None + rss_kb = float(rss_match.group("rss")) / 1024 if rss_match else None + return elapsed_seconds, rss_kb + + +def _run_subprocess_mutation( + engine: ModifiableEngine, + template: Path, + output: Path, + mutations: list[Mutation], +) -> tuple[float, float]: + """Run one isolated mutation and return elapsed milliseconds and RSS kilobytes.""" + command = [ + "/usr/bin/time", + "-l", + sys.executable, + "-c", + _DRIVER, + engine.name, + str(template), + str(output), + json.dumps(mutations, sort_keys=True), + ] + completed = subprocess.run(command, text=True, capture_output=True, check=False) + elapsed_seconds, peak_rss_kb = _parse_time_output(completed.stderr) + if completed.returncode != 0: + message = ( + completed.stderr.strip() + or completed.stdout.strip() + or "mutation driver failed" + ) + raise RuntimeError(message) + if elapsed_seconds is None or peak_rss_kb is None: + raise RuntimeError( + f"Unable to parse /usr/bin/time -l output: {completed.stderr.strip()}" + ) + return elapsed_seconds * 1000, peak_rss_kb + + +def _mutations_for_engine(manifest: dict[str, Any], engine_name: str) -> list[Mutation]: + """Materialize the fixture's engine-specific mutation values.""" + first = dict(manifest["mutation"]) + first["value"] = str(first["value"]).replace("", engine_name) + return [first, dict(manifest["second_mutation"])] + + +def _mutations_landed(output: Path, mutations: list[Mutation]) -> bool: + """Verify the requested values after a mutation output is written.""" + try: + workbook = openpyxl.load_workbook(output, data_only=False) + except Exception: + return False + try: + return all( + workbook[str(mutation["sheet"])][str(mutation["cell"])].value + == mutation["value"] + for mutation in mutations + ) + finally: + workbook.close() + + +def run_mutation_suite( + template: Path, output_dir: Path, repeats: int = 3 +) -> dict[str, Any]: + """Benchmark isolated surgical mutations and score package preservation.""" + if repeats < 1: + raise ValueError("repeats must be at least 1") + template = Path(template) + output_dir = Path(output_dir) + if not template.is_file(): + raise FileNotFoundError(template) + manifest_path = template.with_name("manifest.json") + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + output_dir.mkdir(parents=True, exist_ok=True) + + engine_results: dict[str, dict[str, Any]] = {} + for engine in modifiable_engines(): + if not engine.available(): + engine_results[engine.name] = { + "available": False, + "status": "unavailable", + "wall_ms_median": None, + "peak_rss_kb_median": None, + "preservation_score": None, + "details": {"reason": "engine unavailable"}, + } + continue + + engine_dir = output_dir / engine.name + engine_dir.mkdir(parents=True, exist_ok=True) + mutations = _mutations_for_engine(manifest, engine.name) + wall_times: list[float] = [] + peak_rss_values: list[float] = [] + final_output: Path | None = None + try: + for repeat_index in range(repeats): + input_path = engine_dir / f"repeat-{repeat_index + 1}-input.xlsx" + output_path = engine_dir / f"repeat-{repeat_index + 1}-output.xlsx" + shutil.copyfile(template, input_path) + output_path.unlink(missing_ok=True) + wall_ms, peak_rss_kb = _run_subprocess_mutation( + engine, input_path, output_path, mutations + ) + wall_times.append(wall_ms) + peak_rss_values.append(peak_rss_kb) + final_output = output_path + if final_output is None: + raise RuntimeError("mutation suite did not produce an output") + scored = score_preservation(template, final_output) + mutations_landed = _mutations_landed(final_output, mutations) + details = dict(scored["details"]) + details["mutations_landed"] = mutations_landed + if not mutations_landed: + details["integrity_failure"] = ( + "mutated cell values did not match requested values" + ) + engine_results[engine.name] = { + "available": True, + "status": "passed" if mutations_landed else "integrity-failed", + "wall_ms_median": round(statistics.median(wall_times), 3), + "peak_rss_kb_median": round(statistics.median(peak_rss_values), 3), + "preservation_score": scored["preservation_score"] + if mutations_landed + else 0.0, + "details": details, + } + except Exception as error: + engine_results[engine.name] = { + "available": True, + "status": "failed", + "wall_ms_median": None, + "peak_rss_kb_median": None, + "preservation_score": None, + "details": {"error": f"{type(error).__name__}: {error}"}, + } + + return { + "metadata": { + "template_sha256": _sha256_file(template), + "repeats": repeats, + "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), + "platform": os.uname().sysname, + }, + "engines": engine_results, + } diff --git a/src/excelbench/harness/runner.py b/src/excelbench/harness/runner.py index 773a4de..8d02dbc 100644 --- a/src/excelbench/harness/runner.py +++ b/src/excelbench/harness/runner.py @@ -194,7 +194,9 @@ def run_benchmark( "(fixtures/excel/tier2/15_pivot_tables.xlsx)." ) all_scores.append(score) - print(f" {adapter.name}: read={score.read_score}, write={score.write_score}") + print( + f" {adapter.name}: read={score.read_score}, write={score.write_score}" + ) return BenchmarkResults( metadata=metadata, @@ -292,7 +294,12 @@ def _annotate_known_limitations(score: FeatureScore) -> FeatureScore: if limitation is None: return score side, note = limitation - if side == "read" and score.read_score is not None and score.read_score < 3 and not score.notes: + if ( + side == "read" + and score.read_score is not None + and score.read_score < 3 + and not score.notes + ): score.notes = note if ( side == "write" @@ -493,6 +500,12 @@ def test_read_case( actual = read_comment_actual(adapter, workbook, sheet, expected) elif feature == "freeze_panes": actual = read_freeze_panes_actual(adapter, workbook, sheet, expected) + elif feature == "sheet_protection": + actual = read_sheet_protection_actual(adapter, workbook, sheet) + elif feature == "page_setup": + actual = read_page_setup_actual(adapter, workbook, sheet) + elif feature == "chart_anchor": + actual = read_chart_anchor_actual(adapter, workbook, sheet) else: actual = {"error": f"Unknown feature: {feature}"} @@ -502,6 +515,10 @@ def test_read_case( cmp_expected = expected if feature == "conditional_formatting": cmp_expected = _strip_cf_priority(expected) + if feature == "sheet_protection": + cmp_expected = _strip_protection_password(cmp_expected) + if feature == "chart_anchor": + cmp_expected = _strip_chart_write_refs(cmp_expected) passed = compare_results(cmp_expected, actual) return TestResult( @@ -770,7 +787,9 @@ def read_merged_cells_actual( if match: start_cell, end_cell = _split_range(match) if expected.get("top_left_value") is not None: - result["top_left_value"] = _read_cell_scalar(adapter, workbook, sheet, start_cell) + result["top_left_value"] = _read_cell_scalar( + adapter, workbook, sheet, start_cell + ) if expected.get("non_top_left_nonempty") is not None: count = 0 for cell in _cells_in_range(start_cell, end_cell): @@ -782,12 +801,16 @@ def read_merged_cells_actual( result["non_top_left_nonempty"] = count if expected.get("top_left_bg_color") is not None: fmt = adapter.read_cell_format(workbook, sheet, start_cell) - result["top_left_bg_color"] = fmt.bg_color.upper() if fmt.bg_color else None + result["top_left_bg_color"] = ( + fmt.bg_color.upper() if fmt.bg_color else None + ) if expected.get("non_top_left_bg_color") is not None: other = _first_non_top_left_cell(start_cell, end_cell) if other: fmt = adapter.read_cell_format(workbook, sheet, other) - result["non_top_left_bg_color"] = fmt.bg_color.upper() if fmt.bg_color else None + result["non_top_left_bg_color"] = ( + fmt.bg_color.upper() if fmt.bg_color else None + ) return result @@ -803,6 +826,40 @@ def _strip_cf_priority(expected: JSONDict) -> JSONDict: return out +def _strip_protection_password(expected: JSONDict) -> JSONDict: + """Return a copy of *expected* without the write-only protection password. + + The manifest carries the plaintext password so the write lane can apply + it; readers can only observe ``password_hash_present``. + """ + wrapped = "protection" in expected + protection = expected.get("protection", expected) + if not isinstance(protection, dict) or "password" not in protection: + return expected + stripped = {k: v for k, v in protection.items() if k != "password"} + if wrapped: + return {**expected, "protection": stripped} + return stripped + + +def _strip_chart_write_refs(expected: JSONDict) -> JSONDict: + """Return a copy of *expected* without write-only chart series refs. + + ``data_ref``/``categories_ref`` feed ``add_chart_with_anchor`` in the + write lane; ``read_chart_anchors`` only reports type/anchor/cells. + """ + charts = expected.get("charts") + if not isinstance(charts, list): + return expected + stripped = [ + {k: v for k, v in chart.items() if k not in ("data_ref", "categories_ref")} + if isinstance(chart, dict) + else chart + for chart in charts + ] + return {**expected, "charts": stripped} + + def read_conditional_format_actual( adapter: ExcelAdapter, workbook: Any, @@ -880,7 +937,11 @@ def read_image_actual( normalized = dict(match) expected_path = expected_rule.get("path") actual_path = normalized.get("path") - if expected_path and isinstance(actual_path, str) and actual_path.startswith("/xl/media/"): + if ( + expected_path + and isinstance(actual_path, str) + and actual_path.startswith("/xl/media/") + ): normalized["path"] = expected_path return {"image": _project_rule(normalized, expected_rule)} @@ -942,6 +1003,36 @@ def read_freeze_panes_actual( return {"freeze": _project_rule(settings, expected_rule)} +def read_sheet_protection_actual( + adapter: ExcelAdapter, + workbook: Any, + sheet: str, +) -> JSONDict: + """Read sheet protection settings and return as comparable dict.""" + settings = adapter.read_sheet_protection(workbook, sheet) + return {"protection": settings} + + +def read_page_setup_actual( + adapter: ExcelAdapter, + workbook: Any, + sheet: str, +) -> JSONDict: + """Read page setup settings and return as comparable dict.""" + settings = adapter.read_page_setup(workbook, sheet) + return {"page_setup": settings} + + +def read_chart_anchor_actual( + adapter: ExcelAdapter, + workbook: Any, + sheet: str, +) -> JSONDict: + """Read chart anchors and return as comparable dict.""" + charts = adapter.read_chart_anchors(workbook, sheet) + return {"charts": charts} + + def _normalize_named_range_refers_to(value: Any) -> str: if value is None: return "" @@ -983,7 +1074,9 @@ def read_named_ranges_actual( expected_scope = expected.get("scope") expected_ref = expected.get("refers_to") expected_ref_norm = ( - _normalize_named_range_refers_to(expected_ref) if isinstance(expected_ref, str) else None + _normalize_named_range_refers_to(expected_ref) + if isinstance(expected_ref, str) + else None ) for nr in all_names: @@ -1128,9 +1221,13 @@ def test_write( adapter, workbook, target_sheet, target_cell, tc.expected ) elif test_file.feature == "formulas": - _write_formula_case(adapter, workbook, target_sheet, target_cell, tc.expected) + _write_formula_case( + adapter, workbook, target_sheet, target_cell, tc.expected + ) elif test_file.feature == "text_formatting": - _write_text_format_case(adapter, workbook, target_sheet, target_cell, tc) + _write_text_format_case( + adapter, workbook, target_sheet, target_cell, tc + ) elif test_file.feature == "background_colors": _write_background_color_case( adapter, @@ -1164,7 +1261,9 @@ def test_write( tc.expected, ) elif test_file.feature == "dimensions": - _write_dimensions_case(adapter, workbook, target_sheet, target_cell, tc) + _write_dimensions_case( + adapter, workbook, target_sheet, target_cell, tc + ) elif test_file.feature == "multiple_sheets": _write_multi_sheet_case( adapter, @@ -1174,15 +1273,23 @@ def test_write( tc.expected, ) elif test_file.feature == "merged_cells": - _write_merged_cells_case(adapter, workbook, target_sheet, tc.expected) + _write_merged_cells_case( + adapter, workbook, target_sheet, tc.expected + ) elif test_file.feature == "conditional_formatting": - _write_conditional_format_case(adapter, workbook, target_sheet, tc.expected) + _write_conditional_format_case( + adapter, workbook, target_sheet, tc.expected + ) elif test_file.feature == "data_validation": - _write_data_validation_case(adapter, workbook, target_sheet, tc.expected) + _write_data_validation_case( + adapter, workbook, target_sheet, tc.expected + ) elif test_file.feature == "hyperlinks": _write_hyperlink_case(adapter, workbook, target_sheet, tc.expected) elif test_file.feature == "named_ranges": - _write_named_range_case(adapter, workbook, target_sheet, tc.expected) + _write_named_range_case( + adapter, workbook, target_sheet, tc.expected + ) elif test_file.feature == "tables": _write_table_case(adapter, workbook, target_sheet, tc.expected) elif test_file.feature == "images": @@ -1192,7 +1299,19 @@ def test_write( elif test_file.feature == "comments": _write_comment_case(adapter, workbook, target_sheet, tc.expected) elif test_file.feature == "freeze_panes": - _write_freeze_panes_case(adapter, workbook, target_sheet, tc.expected) + _write_freeze_panes_case( + adapter, workbook, target_sheet, tc.expected + ) + elif test_file.feature == "sheet_protection": + _write_sheet_protection_case( + adapter, workbook, target_sheet, tc.expected + ) + elif test_file.feature == "page_setup": + _write_page_setup_case(adapter, workbook, target_sheet, tc.expected) + elif test_file.feature == "chart_anchor": + _write_chart_anchor_case( + adapter, workbook, target_sheet, tc.expected + ) adapter.save_workbook(workbook, output_path) except Exception as e: @@ -1380,7 +1499,11 @@ def get_write_verifier_for_feature(feature: str) -> ExcelAdapter: return get_write_verifier() if platform.system() == "Darwin": return OpenpyxlAdapter() - if feature in complex_features and _excel_available() and ExcelOracleAdapter is not None: + if ( + feature in complex_features + and _excel_available() + and ExcelOracleAdapter is not None + ): return ExcelOracleAdapter() return OpenpyxlAdapter() @@ -1418,7 +1541,9 @@ def _collect_sheet_names(test_file: TestFile) -> list[str]: explicit = True break if test_file.feature == "formulas": - sheet_names.extend(_extract_formula_sheet_names(tc.expected.get("formula", ""))) + sheet_names.extend( + _extract_formula_sheet_names(tc.expected.get("formula", "")) + ) if test_file.feature == "conditional_formatting": rule = tc.expected.get("cf_rule", {}) formula = rule.get("formula") @@ -1520,28 +1645,34 @@ def _find_by_key(items: list[JSONDict], key: str, value: Any) -> JSONDict | None def _find_rule(rules: list[JSONDict], expected: JSONDict) -> JSONDict | None: for rule in rules: - if expected.get("range") and _normalize_range(rule.get("range", "")) != _normalize_range( - expected.get("range", "") - ): + if expected.get("range") and _normalize_range( + rule.get("range", "") + ) != _normalize_range(expected.get("range", "")): continue - if expected.get("rule_type") and rule.get("rule_type") != expected.get("rule_type"): + if expected.get("rule_type") and rule.get("rule_type") != expected.get( + "rule_type" + ): continue if expected.get("formula") and rule.get("formula"): - if _normalize_formula(expected["formula"]) != _normalize_formula(rule["formula"]): + if _normalize_formula(expected["formula"]) != _normalize_formula( + rule["formula"] + ): continue return rule return None -def _find_validation(validations: list[JSONDict], expected: JSONDict) -> JSONDict | None: +def _find_validation( + validations: list[JSONDict], expected: JSONDict +) -> JSONDict | None: for validation in validations: if expected.get("range") and _normalize_range( validation.get("range", "") ) != _normalize_range(expected.get("range", "")): continue - if expected.get("validation_type") and validation.get("validation_type") != expected.get( + if expected.get("validation_type") and validation.get( "validation_type" - ): + ) != expected.get("validation_type"): continue if expected.get("formula1"): if _normalize_formula(validation.get("formula1")) != _normalize_formula( @@ -1587,10 +1718,14 @@ def _quote_match(m: re.Match[str]) -> str: return f"='{name}'!{cell_ref}" # Match =SheetName!CellRef where SheetName is not already quoted - return re.sub(r"=([A-Za-z0-9_][A-Za-z0-9_ ]*)!(\$?[A-Z]+\$?[0-9]+)", _quote_match, formula) + return re.sub( + r"=([A-Za-z0-9_][A-Za-z0-9_ ]*)!(\$?[A-Z]+\$?[0-9]+)", _quote_match, formula + ) -def _read_cell_scalar(adapter: ExcelAdapter, workbook: Any, sheet: str, cell: str) -> Any: +def _read_cell_scalar( + adapter: ExcelAdapter, workbook: Any, sheet: str, cell: str +) -> Any: cell_value = adapter.read_cell_value(workbook, sheet, cell) if cell_value.type == CellType.BLANK: return None @@ -1724,8 +1859,12 @@ def _write_cell_value_case( adapter.write_cell_value(workbook, sheet, cell, cell_value) if cell_value.type in (CellType.DATE, CellType.DATETIME): - number_format = "yyyy-mm-dd" if cell_value.type == CellType.DATE else "yyyy-mm-dd hh:mm:ss" - adapter.write_cell_format(workbook, sheet, cell, CellFormat(number_format=number_format)) + number_format = ( + "yyyy-mm-dd" if cell_value.type == CellType.DATE else "yyyy-mm-dd hh:mm:ss" + ) + adapter.write_cell_format( + workbook, sheet, cell, CellFormat(number_format=number_format) + ) def _write_formula_case( @@ -1753,7 +1892,9 @@ def _write_text_format_case( cell, CellValue(type=CellType.STRING, value=test_case.label), ) - adapter.write_cell_format(workbook, sheet, cell, _cell_format_from_expected(test_case.expected)) + adapter.write_cell_format( + workbook, sheet, cell, _cell_format_from_expected(test_case.expected) + ) def _write_background_color_case( @@ -1763,8 +1904,12 @@ def _write_background_color_case( cell: str, expected: JSONDict, ) -> None: - adapter.write_cell_value(workbook, sheet, cell, CellValue(type=CellType.STRING, value="Color")) - adapter.write_cell_format(workbook, sheet, cell, _cell_format_from_expected(expected)) + adapter.write_cell_value( + workbook, sheet, cell, CellValue(type=CellType.STRING, value="Color") + ) + adapter.write_cell_format( + workbook, sheet, cell, _cell_format_from_expected(expected) + ) def _write_number_format_case( @@ -1784,8 +1929,12 @@ def _write_number_format_case( # passes where libraries ignore write_cell_format() but a default date # number format is auto-assigned for native date objects. value = 45326.0 # 2024-02-04 in Excel's 1900 date system. - adapter.write_cell_value(workbook, sheet, cell, CellValue(type=value_type, value=value)) - adapter.write_cell_format(workbook, sheet, cell, _cell_format_from_expected(expected)) + adapter.write_cell_value( + workbook, sheet, cell, CellValue(type=value_type, value=value) + ) + adapter.write_cell_format( + workbook, sheet, cell, _cell_format_from_expected(expected) + ) def _write_alignment_case( @@ -1795,8 +1944,12 @@ def _write_alignment_case( cell: str, expected: JSONDict, ) -> None: - adapter.write_cell_value(workbook, sheet, cell, CellValue(type=CellType.STRING, value="Align")) - adapter.write_cell_format(workbook, sheet, cell, _cell_format_from_expected(expected)) + adapter.write_cell_value( + workbook, sheet, cell, CellValue(type=CellType.STRING, value="Align") + ) + adapter.write_cell_format( + workbook, sheet, cell, _cell_format_from_expected(expected) + ) def _write_border_case( @@ -1806,7 +1959,9 @@ def _write_border_case( cell: str, expected: JSONDict, ) -> None: - adapter.write_cell_value(workbook, sheet, cell, CellValue(type=CellType.STRING, value="Border")) + adapter.write_cell_value( + workbook, sheet, cell, CellValue(type=CellType.STRING, value="Border") + ) adapter.write_cell_border(workbook, sheet, cell, _border_from_expected(expected)) @@ -1818,10 +1973,14 @@ def _write_dimensions_case( test_case: TestCase, ) -> None: if "row_height" in test_case.expected: - adapter.set_row_height(workbook, sheet, test_case.row, test_case.expected["row_height"]) + adapter.set_row_height( + workbook, sheet, test_case.row, test_case.expected["row_height"] + ) if "column_width" in test_case.expected: column = _extract_column(cell) - adapter.set_column_width(workbook, sheet, column, test_case.expected["column_width"]) + adapter.set_column_width( + workbook, sheet, column, test_case.expected["column_width"] + ) def _write_multi_sheet_case( @@ -1903,7 +2062,9 @@ def _write_named_range_case( if "value" in expected: refers_to = expected.get("refers_to") if isinstance(refers_to, str): - loc = _parse_named_range_single_cell(_normalize_named_range_refers_to(refers_to)) + loc = _parse_named_range_single_cell( + _normalize_named_range_refers_to(refers_to) + ) if loc is not None: ref_sheet, ref_cell = loc adapter.write_cell_value( @@ -1986,6 +2147,36 @@ def _write_freeze_panes_case( adapter.set_freeze_panes(workbook, sheet, expected) +def _write_sheet_protection_case( + adapter: ExcelAdapter, + workbook: Any, + sheet: str, + expected: JSONDict, +) -> None: + settings = expected.get("protection", expected) + adapter.set_sheet_protection(workbook, sheet, settings) + + +def _write_page_setup_case( + adapter: ExcelAdapter, + workbook: Any, + sheet: str, + expected: JSONDict, +) -> None: + settings = expected.get("page_setup", expected) + adapter.set_page_setup(workbook, sheet, settings) + + +def _write_chart_anchor_case( + adapter: ExcelAdapter, + workbook: Any, + sheet: str, + expected: JSONDict, +) -> None: + for chart in expected.get("charts", []): + adapter.add_chart_with_anchor(workbook, sheet, chart) + + def calculate_score(results: list[TestResult]) -> int: """Calculate fidelity score from test results. diff --git a/src/excelbench/modifiable.py b/src/excelbench/modifiable.py new file mode 100644 index 0000000..590ed6e --- /dev/null +++ b/src/excelbench/modifiable.py @@ -0,0 +1,194 @@ +"""Workbook engines used by the surgical mutation benchmark.""" + +from __future__ import annotations + +import shutil +from pathlib import Path +from typing import Any, Protocol + +from excelbench.harness.external_oracles import ( + ExternalOracleRequest, + external_oracle_catalog, + run_external_oracle, +) + +try: + import openpyxl as _openpyxl +except ImportError: # pragma: no cover - optional dependency guard + _openpyxl = None + +try: + import wolfxl as _wolfxl +except ImportError: # pragma: no cover - optional dependency guard + _wolfxl = None + +try: + import aspose.cells_foss as _aspose_cells_foss +except ImportError: # pragma: no cover - optional dependency guard + _aspose_cells_foss = None + +Mutation = dict[str, Any] +_REPO_ROOT = Path(__file__).resolve().parents[2] + + +class ModifiableEngine(Protocol): + """Protocol implemented by engines that can modify an existing workbook.""" + + name: str + + def available(self) -> bool: + """Return whether this engine is installed and usable.""" + + def mutate(self, template: Path, output: Path, mutations: list[Mutation]) -> None: + """Apply all mutations to a template workbook and save the output.""" + + +def _mutation_target(mutation: Mutation) -> tuple[str, str, Any]: + """Validate and unpack one mutation payload.""" + try: + sheet = mutation["sheet"] + cell = mutation["cell"] + value = mutation["value"] + except KeyError as error: + raise ValueError( + f"Mutation is missing required key: {error.args[0]}" + ) from error + if not isinstance(sheet, str) or not sheet: + raise ValueError("Mutation sheet must be a non-empty string") + if not isinstance(cell, str) or not cell: + raise ValueError("Mutation cell must be a non-empty string") + return sheet, cell, value + + +class OpenpyxlEngine: + """In-place workbook mutation through OpenPyXL.""" + + name = "openpyxl" + + def available(self) -> bool: + """Return whether OpenPyXL can be imported.""" + return _openpyxl is not None + + def mutate(self, template: Path, output: Path, mutations: list[Mutation]) -> None: + """Apply mutations with OpenPyXL and save a new workbook package.""" + if _openpyxl is None: + raise RuntimeError("openpyxl is not installed") + output.parent.mkdir(parents=True, exist_ok=True) + workbook = _openpyxl.load_workbook(template) + try: + for mutation in mutations: + sheet, cell, value = _mutation_target(mutation) + workbook[sheet][cell] = value + workbook.save(output) + finally: + workbook.close() + + +class WolfxlEngine: + """In-place workbook mutation through WolfXL modify mode.""" + + name = "wolfxl" + + def available(self) -> bool: + """Return whether WolfXL can be imported.""" + return _wolfxl is not None + + def mutate(self, template: Path, output: Path, mutations: list[Mutation]) -> None: + """Apply mutations with WolfXL's public modify-mode API.""" + if _wolfxl is None: + raise RuntimeError("wolfxl is not installed") + output.parent.mkdir(parents=True, exist_ok=True) + workbook = _wolfxl.load_workbook(template, modify=True) + for mutation in mutations: + sheet, cell, value = _mutation_target(mutation) + workbook[sheet][cell].value = value + workbook.save(output) + + +class AsposeFossEngine: + """In-place workbook mutation through aspose-cells-foss.""" + + name = "aspose-cells-foss" + + def available(self) -> bool: + """Return whether aspose-cells-foss can be imported.""" + return _aspose_cells_foss is not None + + def mutate(self, template: Path, output: Path, mutations: list[Mutation]) -> None: + """Apply mutations with aspose-cells-foss and save a new workbook package.""" + if _aspose_cells_foss is None: + raise RuntimeError("aspose-cells-foss is not installed") + output.parent.mkdir(parents=True, exist_ok=True) + workbook = _aspose_cells_foss.Workbook(str(template)) + for mutation in mutations: + sheet, cell, value = _mutation_target(mutation) + worksheet = next( + ( + candidate + for candidate in workbook.worksheets + if candidate.name == sheet + ), + None, + ) + if worksheet is None: + raise KeyError(f"Worksheet not found: {sheet}") + worksheet.cells.get_cell_by_name(cell).value = value + workbook.save(str(output)) + + +class ZavoraEngine: + """In-place workbook mutation through the optional Zavora oracle helper.""" + + name = "zavora-xlsx" + + def available(self) -> bool: + """Return whether the Zavora helper command and source are available.""" + return external_oracle_catalog(_REPO_ROOT)["zavora"].is_available() + + def mutate(self, template: Path, output: Path, mutations: list[Mutation]) -> None: + """Apply mutations through chained external-oracle requests.""" + tool = external_oracle_catalog(_REPO_ROOT)["zavora"] + if not tool.is_available(): + raise RuntimeError("zavora external oracle is unavailable") + output.parent.mkdir(parents=True, exist_ok=True) + if not mutations: + shutil.copyfile(template, output) + return + + intermediate_paths: list[Path] = [] + input_path = template.resolve() + try: + for index, mutation in enumerate(mutations): + sheet, cell, value = _mutation_target(mutation) + is_last = index == len(mutations) - 1 + next_path = output.resolve() + if not is_last: + next_path = output.with_name( + f".{output.stem}.mutation-{index}{output.suffix}" + ).resolve() + intermediate_paths.append(next_path) + request = ExternalOracleRequest( + fixture_id="mutation-template", + operation="mutate", + payload={"sheet": sheet, "cell": cell, "value": value}, + input_path=input_path, + output_path=next_path, + ) + result = run_external_oracle(tool, request) + if not result.passed: + detail = ( + result.notes + or result.stderr + or result.stdout + or "unknown oracle failure" + ) + raise RuntimeError(f"zavora mutation failed: {detail.strip()}") + input_path = next_path + finally: + for intermediate_path in intermediate_paths: + intermediate_path.unlink(missing_ok=True) + + +def modifiable_engines() -> list[ModifiableEngine]: + """Return the fixed engine registry used by the mutation suite.""" + return [OpenpyxlEngine(), WolfxlEngine(), AsposeFossEngine(), ZavoraEngine()] diff --git a/src/excelbench/results/calc_renderer.py b/src/excelbench/results/calc_renderer.py new file mode 100644 index 0000000..5e55b88 --- /dev/null +++ b/src/excelbench/results/calc_renderer.py @@ -0,0 +1,62 @@ +"""Render formula recalculation comparison results.""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + + +def render_calc_results(results: dict[str, Any], output_dir: Path) -> None: + """Write calculation results as JSON and a concise Markdown report.""" + output_dir.mkdir(parents=True, exist_ok=True) + (output_dir / "results.json").write_text( + json.dumps(results, indent=2, sort_keys=True) + "\n" + ) + (output_dir / "README.md").write_text(_render_markdown(results)) + + +def _render_markdown(results: dict[str, Any]) -> str: + engines = results.get("engines", {}) + lines = [ + "# ExcelBench Formula Recalculation Results", + "", + f"Oracle: {results.get('oracle') or 'unknown'}", + "", + "Formula values are compared with absolute tolerance 1e-6 or relative tolerance 1e-9 " + "for numbers; strings and booleans compare exactly.", + "", + "| Engine | Status | Matched/total | First mismatches |", + "| --- | --- | --- | --- |", + ] + if not isinstance(engines, dict): + engines = {} + for name, result in engines.items(): + if not isinstance(result, dict): + continue + mismatches = result.get("mismatched_cells", []) + mismatch_text = _mismatch_text(mismatches) + lines.append( + "| " + f"{name} | {result.get('status', 'unknown')} | " + f"{result.get('matched', 0)}/{result.get('total', 0)} | {mismatch_text} |" + ) + reason = result.get("reason") + if reason: + lines.extend(["", f"{name}: {reason}"]) + lines.append("") + return "\n".join(lines) + + +def _mismatch_text(mismatches: Any) -> str: + if not isinstance(mismatches, list) or not mismatches: + return "—" + rendered: list[str] = [] + for mismatch in mismatches[:10]: + if not isinstance(mismatch, dict): + continue + rendered.append( + f"{mismatch.get('cell')}: expected {mismatch.get('expected')!r}, " + f"actual {mismatch.get('actual')!r}" + ) + return "
".join(rendered).replace("|", "\\|") or "—" diff --git a/src/excelbench/results/mutation_renderer.py b/src/excelbench/results/mutation_renderer.py new file mode 100644 index 0000000..9c3c8ea --- /dev/null +++ b/src/excelbench/results/mutation_renderer.py @@ -0,0 +1,81 @@ +"""Rendering for surgical workbook mutation benchmark results.""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + + +def _format_number(value: object, suffix: str = "") -> str: + """Format an optional benchmark number for a Markdown cell.""" + if isinstance(value, int | float): + return f"{value:.3f}{suffix}" + return "—" + + +def _verdict(result: dict[str, Any]) -> str: + """Return a concise status label for an engine result.""" + status = result.get("status") + if status == "unavailable": + return "Unavailable" + if status == "failed": + return "Failed" + if status == "integrity-failed": + return "Mutation integrity failed" + if result.get("preservation_score") == 100: + return "Preserved" + return "Loss detected" + + +def render_mutation_report(results: dict[str, Any], output_dir: Path) -> None: + """Write ``results.json`` and a compact Markdown comparison report.""" + output_dir = Path(output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + (output_dir / "results.json").write_text( + json.dumps(results, indent=2, sort_keys=True) + "\n", encoding="utf-8" + ) + + metadata = results.get("metadata", {}) + engine_results = results.get("engines", {}) + lines = [ + "# ExcelBench Mutation Results", + "", + f"*Generated: {metadata.get('timestamp', 'unknown')}*", + f"*Template SHA-256: {metadata.get('template_sha256', 'unknown')}*", + f"*Repeats: {metadata.get('repeats', 'unknown')}*", + "", + "## Comparison", + "", + "| Engine | Wall ms | Peak RSS KB | Preservation score | Lost parts | Verdict |", + "|--------|---------|-------------|--------------------|------------|---------|", + ] + for engine_name in sorted(engine_results): + result = engine_results[engine_name] + details = result.get("details", {}) + lost_parts = details.get("lost_parts", []) + lost_count = len(lost_parts) if isinstance(lost_parts, list) else "—" + score = result.get("preservation_score") + score_text = _format_number(score) if isinstance(score, int | float) else "—" + lines.append( + f"| {engine_name} | {_format_number(result.get('wall_ms_median'))} | " + f"{_format_number(result.get('peak_rss_kb_median'))} | {score_text} | " + f"{lost_count} | {_verdict(result)} |" + ) + lines.extend( + [ + "", + "## Notes", + "", + ( + "Wall time and peak RSS are measured in isolated subprocesses " + "with macOS `/usr/bin/time -l`." + ), + ( + "Preservation compares each output package against the original template. " + "It does not measure formula recalculation or rendering." + ), + "", + ] + ) + (output_dir / "README.md").write_text("\n".join(lines), encoding="utf-8") diff --git a/tests/test_aspose_cells_foss_adapter.py b/tests/test_aspose_cells_foss_adapter.py new file mode 100644 index 0000000..a0d61a9 --- /dev/null +++ b/tests/test_aspose_cells_foss_adapter.py @@ -0,0 +1,125 @@ +"""Tests for the aspose-cells-foss adapter using its installed implementation.""" + +from __future__ import annotations + +from pathlib import Path + +import pytest + +from excelbench.harness.adapters.aspose_cells_foss_adapter import AsposeCellsFossAdapter +from excelbench.harness.adapters.base import UnsupportedAdapterOperationError +from excelbench.models import ( + BorderEdge, + BorderInfo, + BorderStyle, + CellFormat, + CellType, + CellValue, +) + + +@pytest.fixture +def adapter() -> AsposeCellsFossAdapter: + return AsposeCellsFossAdapter() + + +def test_values_formats_and_dimensions_round_trip( + adapter: AsposeCellsFossAdapter, tmp_path: Path +) -> None: + """Values, formula text, formatting, borders, and dimensions survive an XLSX round trip.""" + path = tmp_path / "aspose-cells-foss.xlsx" + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "Data") + adapter.write_cell_value( + workbook, "Data", "A1", CellValue(type=CellType.STRING, value="hello") + ) + adapter.write_cell_value( + workbook, "Data", "B1", CellValue(type=CellType.NUMBER, value=42.5) + ) + adapter.write_cell_value( + workbook, + "Data", + "C1", + CellValue(type=CellType.FORMULA, value=None, formula="=B1*2"), + ) + adapter.write_cell_format( + workbook, + "Data", + "A1", + CellFormat( + bold=True, + italic=True, + underline="single", + strikethrough=True, + font_name="Arial", + font_size=16, + font_color="#FF0000", + bg_color="#FFFF00", + number_format="0.00", + h_align="center", + v_align="top", + wrap=True, + rotation=45, + indent=2, + ), + ) + adapter.write_cell_border( + workbook, + "Data", + "A1", + BorderInfo( + top=BorderEdge(style=BorderStyle.THIN, color="#FF0000"), + bottom=BorderEdge(style=BorderStyle.DOUBLE, color="#00FF00"), + ), + ) + adapter.set_row_height(workbook, "Data", 1, 30) + adapter.set_column_width(workbook, "Data", "A", 20) + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + assert adapter.get_sheet_names(reopened) == ["Data"] + assert adapter.read_cell_value(reopened, "Data", "A1") == CellValue( + type=CellType.STRING, value="hello" + ) + assert adapter.read_cell_value(reopened, "Data", "B1") == CellValue( + type=CellType.NUMBER, value=42.5 + ) + formula = adapter.read_cell_value(reopened, "Data", "C1") + assert formula.type == CellType.FORMULA + assert formula.formula == "=B1*2" + cell_format = adapter.read_cell_format(reopened, "Data", "A1") + assert cell_format.bold is True + assert cell_format.italic is True + assert cell_format.underline == "single" + assert cell_format.strikethrough is True + assert cell_format.font_name == "Arial" + assert cell_format.font_size == 16 + assert cell_format.font_color == "#FF0000" + assert cell_format.bg_color == "#FFFF00" + assert cell_format.number_format == "0.00" + assert cell_format.h_align == "center" + assert cell_format.v_align == "top" + assert cell_format.wrap is True + assert cell_format.rotation == 45 + assert cell_format.indent == 2 + border = adapter.read_cell_border(reopened, "Data", "A1") + assert border.top == BorderEdge(style=BorderStyle.THIN, color="#FF0000") + assert border.bottom == BorderEdge(style=BorderStyle.DOUBLE, color="#00FF00") + assert adapter.read_row_height(reopened, "Data", 1) == 30 + assert adapter.read_column_width(reopened, "Data", "A") == 20 + adapter.close_workbook(reopened) + + +def test_pivot_operations_raise_structured_unsupported_error( + adapter: AsposeCellsFossAdapter, +) -> None: + """The adapter reports its unsupported pivot capability without a silent no-op.""" + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "Data") + + with pytest.raises(UnsupportedAdapterOperationError) as error: + adapter.add_pivot_table(workbook, "Data", {}) + + assert error.value.adapter == "aspose-cells-foss" + assert error.value.operation == "add_pivot_table" + assert "no pivot-table API" in error.value.reason diff --git a/tests/test_calc_suite.py b/tests/test_calc_suite.py new file mode 100644 index 0000000..5ac730f --- /dev/null +++ b/tests/test_calc_suite.py @@ -0,0 +1,86 @@ +"""Tests for the Formula Recalculation benchmark tier.""" + +from __future__ import annotations + +import json +from collections.abc import Callable +from importlib.util import module_from_spec, spec_from_file_location +from pathlib import Path +from types import ModuleType +from typing import Any, cast + +from excelbench.harness.calc import ( + AsposeCellsFossCalcEngine, + LibreOfficeCalcEngine, + WolfXLCalcEngine, + formula_cells, + values_match, +) + +FIXTURE = Path("fixtures/calc/financial_model.xlsx") +EXPECTED = Path("fixtures/calc/expected_values.json") + + +def _load_fixture_builder() -> Callable[[Path, Path], dict[str, Any]]: + script_path = Path("scripts/build_calc_fixture.py") + spec = spec_from_file_location("build_calc_fixture", script_path) + assert spec is not None and spec.loader is not None + module = module_from_spec(spec) + assert isinstance(module, ModuleType) + spec.loader.exec_module(module) + return cast(Callable[[Path, Path], dict[str, Any]], module.build_fixture) + + +build_fixture = _load_fixture_builder() + + +def test_builder_regenerates_identical_expected_json(tmp_path: Path) -> None: + fixture = tmp_path / "financial_model.xlsx" + expected = tmp_path / "expected_values.json" + + first = build_fixture(fixture, expected) + first_text = expected.read_text() + second = build_fixture(fixture, expected) + + assert second == first + assert expected.read_text() == first_text + + +def test_expected_values_cover_every_formula_cell() -> None: + expected = json.loads(EXPECTED.read_text()) + + assert set(expected["cells"]) == set(formula_cells(FIXTURE)) + assert 80 <= len(expected["cells"]) <= 140 + assert all( + cell["type"] in {"number", "string", "bool"} + for cell in expected["cells"].values() + ) + + +def test_value_comparison_respects_tolerance_and_scalar_types() -> None: + assert values_match(10.0, 10.0000005) + assert values_match(1_000_000_000.0, 1_000_000_000.5) + assert not values_match(10.0, 10.000002) + assert values_match("exact", "exact") + assert not values_match("exact", "different") + assert values_match(True, True) + assert not values_match(True, 1) + + +def test_local_wolfxl_and_libreoffice_engines_calculate(tmp_path: Path) -> None: + wolfxl_result = WolfXLCalcEngine().calculate(FIXTURE, tmp_path / "wolfxl.xlsx") + libreoffice_result = LibreOfficeCalcEngine().calculate( + FIXTURE, tmp_path / "libreoffice.xlsx" + ) + + assert wolfxl_result["status"] == "passed", wolfxl_result["reason"] + assert libreoffice_result["status"] == "passed", libreoffice_result["reason"] + + +def test_aspose_engine_reports_unsupported_formulas_without_raising( + tmp_path: Path, +) -> None: + result = AsposeCellsFossCalcEngine().calculate(FIXTURE, tmp_path / "aspose.xlsx") + + assert result["status"] in {"failed", "unavailable"} + assert result["reason"] diff --git a/tests/test_external_oracles.py b/tests/test_external_oracles.py index dbddaf2..16f216a 100644 --- a/tests/test_external_oracles.py +++ b/tests/test_external_oracles.py @@ -42,7 +42,10 @@ def test_catalog_lists_planned_external_oracles() -> None: "exceljs", "closedxml", "npoi", + "zavora", } + assert catalog["zavora"].language == "rust" + assert "calculate" in catalog["zavora"].capabilities assert "pivots" in catalog["excelize"].capabilities assert "open_save_validate" in catalog["libreoffice"].capabilities assert "data_validations" in catalog["apache-poi"].capabilities diff --git a/tests/test_mutation_suite.py b/tests/test_mutation_suite.py new file mode 100644 index 0000000..9f79a31 --- /dev/null +++ b/tests/test_mutation_suite.py @@ -0,0 +1,195 @@ +"""Tests for the surgical template-mutation benchmark.""" + +from __future__ import annotations + +import hashlib +import subprocess +import sys +from pathlib import Path +from zipfile import ZIP_DEFLATED, ZipFile + +import openpyxl + +from excelbench.harness.mutation import score_preservation +from excelbench.modifiable import modifiable_engines +from excelbench.results.mutation_renderer import render_mutation_report + +REPO_ROOT = Path(__file__).resolve().parents[1] +BUILDER = REPO_ROOT / "scripts" / "build_mutation_template.py" +TEMPLATE = REPO_ROOT / "fixtures" / "mutation" / "template_corporate_model.xlsx" +SOFFICE = Path("/opt/homebrew/bin/soffice") + + +def _sha256(path: Path) -> str: + """Return the full-file SHA-256 digest.""" + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def _content_types() -> bytes: + """Build minimum valid content type declarations for synthetic packages.""" + return ( + b""" + + + +""" + ) + + +def _relationship_xml(target: str) -> bytes: + """Build a workbook relationship XML part targeting one worksheet.""" + return f""" + + +""".encode() + + +def _write_synthetic_package( + path: Path, + *, + include_custom_xml: bool = True, + table_parts: bool = True, + target: str = "worksheets/sheet1.xml", +) -> None: + """Write a small package that exercises preservation scorer failure modes.""" + sheet_tail = ( + '' + if table_parts + else "" + ) + sheet_xml = ( + '' + f"{sheet_tail}" + ).encode() + parts = { + "[Content_Types].xml": _content_types(), + "_rels/.rels": b'', + "xl/workbook.xml": b"", + "xl/_rels/workbook.xml.rels": _relationship_xml(target), + "xl/worksheets/sheet1.xml": sheet_xml, + "xl/tables/table1.xml": b"", + } + if include_custom_xml: + parts["customXml/item1.xml"] = b"stable" + with ZipFile(path, "w", compression=ZIP_DEFLATED) as archive: + for name, payload in parts.items(): + archive.writestr(name, payload) + + +def test_builder_is_byte_stable() -> None: + """Repeated generation writes the same package bytes.""" + subprocess.run([sys.executable, str(BUILDER)], cwd=REPO_ROOT, check=True) + first_digest = _sha256(TEMPLATE) + subprocess.run([sys.executable, str(BUILDER)], cwd=REPO_ROOT, check=True) + assert _sha256(TEMPLATE) == first_digest + + +def test_template_opens_in_openpyxl_and_libreoffice(tmp_path: Path) -> None: + """The committed fixture parses and LibreOffice renders it to PDF.""" + workbook = openpyxl.load_workbook(TEMPLATE) + try: + assert workbook.sheetnames == ["Inputs", "Schedule", "Summary"] + assert workbook["Inputs"]["B2"].value is not None + finally: + workbook.close() + + completed = subprocess.run( + [ + str(SOFFICE), + "--headless", + "--convert-to", + "pdf", + "--outdir", + str(tmp_path), + str(TEMPLATE), + ], + text=True, + capture_output=True, + check=False, + ) + assert completed.returncode == 0, completed.stderr + assert (tmp_path / "template_corporate_model.pdf").is_file() + + +def test_preservation_scorer_reports_lost_custom_part(tmp_path: Path) -> None: + """A dropped package part reduces the structural score.""" + template = tmp_path / "template.xlsx" + output = tmp_path / "output.xlsx" + _write_synthetic_package(template) + _write_synthetic_package(output, include_custom_xml=False) + + result = score_preservation(template, output) + + assert "customXml/item1.xml" in result["details"]["lost_parts"] + assert result["details"]["customXml_identical"] is False + assert result["preservation_score"] < 100 + + +def test_preservation_scorer_reports_dangling_relationship(tmp_path: Path) -> None: + """A relationship to a missing worksheet is reported as an integrity error.""" + template = tmp_path / "template.xlsx" + output = tmp_path / "output.xlsx" + _write_synthetic_package(template) + _write_synthetic_package(output, target="worksheets/missing.xml") + + result = score_preservation(template, output) + + assert result["details"]["dangling_rels"] == [ + "xl/_rels/workbook.xml.rels: xl/worksheets/missing.xml" + ] + assert result["preservation_score"] < 100 + + +def test_preservation_scorer_reports_dropped_table_parts(tmp_path: Path) -> None: + """Dropping a worksheet table declaration reduces the element score.""" + template = tmp_path / "template.xlsx" + output = tmp_path / "output.xlsx" + _write_synthetic_package(template) + _write_synthetic_package(output, table_parts=False) + + result = score_preservation(template, output) + + assert any( + entry["element"] == "tableParts" + and entry["present_in_original"] + and not entry["present_in_output"] + for entry in result["details"]["element_diffs"] + ) + assert result["preservation_score"] < 100 + + +def test_engine_registry_exposes_availability_flags() -> None: + """Every supported mutation engine reports an explicit availability flag.""" + engines = {engine.name: engine.available() for engine in modifiable_engines()} + + assert set(engines) == {"openpyxl", "wolfxl", "aspose-cells-foss", "zavora-xlsx"} + assert all(isinstance(available, bool) for available in engines.values()) + + +def test_renderer_writes_comparison_files(tmp_path: Path) -> None: + """The renderer writes machine-readable and concise Markdown reports.""" + results = { + "metadata": { + "template_sha256": "abc", + "repeats": 3, + "timestamp": "2026-01-01T00:00:00Z", + }, + "engines": { + "openpyxl": { + "status": "passed", + "wall_ms_median": 12.5, + "peak_rss_kb_median": 2048.0, + "preservation_score": 90.0, + "details": {"lost_parts": ["customXml/item1.xml"]}, + } + }, + } + + render_mutation_report(results, tmp_path) + + assert (tmp_path / "results.json").is_file() + assert "| openpyxl | 12.500 | 2048.000 | 90.000 | 1 | Loss detected |" in ( + tmp_path / "README.md" + ).read_text(encoding="utf-8") diff --git a/tests/test_tier4_handlers.py b/tests/test_tier4_handlers.py new file mode 100644 index 0000000..653e487 --- /dev/null +++ b/tests/test_tier4_handlers.py @@ -0,0 +1,206 @@ +"""Tests for Tier-4 handlers: sheet_protection, page_setup, chart_anchor. + +Builds the Tier-4 structural fixtures into a temp directory via +scripts/build_tier4_fixtures.py, assembles a benchmark directory from the +generated manifest fragment, and runs the full read + write lanes against +OpenpyxlAdapter — proving the runner dispatch, fixtures, and openpyxl +verifier chain end to end. Also checks that adapters lacking the Tier-4 +methods yield structured failure results instead of crashes. +""" + +from __future__ import annotations + +import importlib.util +import shutil +import sys +from pathlib import Path +from types import ModuleType +from typing import Any + +from excelbench.generator.generate import load_manifest +from excelbench.harness.adapters.base import ReadOnlyAdapter +from excelbench.harness.adapters.openpyxl_adapter import OpenpyxlAdapter +from excelbench.harness.runner import run_benchmark +from excelbench.models import ( + BorderInfo, + CellFormat, + CellValue, + DiagnosticCategory, + LibraryInfo, +) + +REPO_ROOT = Path(__file__).resolve().parent.parent +BUILDER_PATH = REPO_ROOT / "scripts" / "build_tier4_fixtures.py" + +TIER4_FEATURES = ["sheet_protection", "page_setup", "chart_anchor"] +CASE_COUNTS = {"sheet_protection": 3, "page_setup": 3, "chart_anchor": 2} + + +def _load_builder() -> ModuleType: + spec = importlib.util.spec_from_file_location("build_tier4_fixtures", BUILDER_PATH) + assert spec is not None and spec.loader is not None + module = importlib.util.module_from_spec(spec) + sys.modules["build_tier4_fixtures"] = module + spec.loader.exec_module(module) + return module + + +def _build_bench_dir(tmp_path: Path) -> Path: + """Build Tier-4 fixtures into tmp and assemble a runnable benchmark dir.""" + builder = _load_builder() + fixtures_root = tmp_path / "fixtures" + fragment_path = builder.build_all(fixtures_root) + assert fragment_path.exists() + + bench_dir = tmp_path / "bench" + bench_dir.mkdir() + shutil.copytree(fixtures_root / "tier4", bench_dir / "tier4") + shutil.copy(fragment_path, bench_dir / "manifest.json") + return bench_dir + + +class TestTier4Benchmark: + def test_openpyxl_read_and_write_scores(self, tmp_path: Path) -> None: + bench_dir = _build_bench_dir(tmp_path) + + results = run_benchmark( + bench_dir, adapters=[OpenpyxlAdapter()], features=TIER4_FEATURES + ) + + by_feature = {score.feature: score for score in results.scores} + assert set(by_feature) == set(TIER4_FEATURES) + for feature in TIER4_FEATURES: + score = by_feature[feature] + failures = [r for r in score.test_results if not r.passed] + assert score.read_score == 3, ( + f"{feature} read failures: {[(r.test_case_id, r.actual) for r in failures]}" + ) + assert score.write_score == 3, ( + f"{feature} write failures: {[(r.test_case_id, r.actual) for r in failures]}" + ) + + def test_fragment_loads_as_manifest(self, tmp_path: Path) -> None: + builder = _load_builder() + fragment_path = builder.build_all(tmp_path) + + manifest = load_manifest(fragment_path) + + assert [f.feature for f in manifest.files] == TIER4_FEATURES + for test_file in manifest.files: + assert test_file.tier == 4 + assert test_file.file_format == "xlsx" + for test_file in manifest.files: + assert len(test_file.test_cases) == CASE_COUNTS[test_file.feature] + if test_file.feature == "chart_anchor": + assert all(tc.sheet is None for tc in test_file.test_cases) + else: + assert all( + tc.sheet and tc.sheet.startswith(test_file.feature) + for tc in test_file.test_cases + ) + protection = manifest.files[0] + assert {tc.id for tc in protection.test_cases} == { + "prot_basic", + "prot_password", + "prot_granular", + } + # The write-only password must ride along in the manifest payload. + password_case = next( + tc for tc in protection.test_cases if tc.id == "prot_password" + ) + assert password_case.expected["protection"]["password"] == "bench-secret" + + +class _Tier3OnlyReader(ReadOnlyAdapter): + """Read-only adapter that implements every pre-Tier-4 read and nothing else.""" + + def __init__(self) -> None: + self._inner = OpenpyxlAdapter() + + @property + def info(self) -> LibraryInfo: + return LibraryInfo( + name="tier3-only-reader", + version="0", + language="python", + capabilities={"read"}, + ) + + def open_workbook(self, path: Path) -> Any: + return self._inner.open_workbook(path) + + def close_workbook(self, workbook: Any) -> None: + self._inner.close_workbook(workbook) + + def get_sheet_names(self, workbook: Any) -> list[str]: + return self._inner.get_sheet_names(workbook) + + def read_cell_value(self, workbook: Any, sheet: str, cell: str) -> CellValue: + return self._inner.read_cell_value(workbook, sheet, cell) + + def read_cell_format(self, workbook: Any, sheet: str, cell: str) -> CellFormat: + return self._inner.read_cell_format(workbook, sheet, cell) + + def read_cell_border(self, workbook: Any, sheet: str, cell: str) -> BorderInfo: + return self._inner.read_cell_border(workbook, sheet, cell) + + def read_row_height(self, workbook: Any, sheet: str, row: int) -> float | None: + return self._inner.read_row_height(workbook, sheet, row) + + def read_column_width(self, workbook: Any, sheet: str, column: str) -> float | None: + return self._inner.read_column_width(workbook, sheet, column) + + def read_merged_ranges(self, workbook: Any, sheet: str) -> list[str]: + return self._inner.read_merged_ranges(workbook, sheet) + + def read_conditional_formats( + self, workbook: Any, sheet: str + ) -> list[dict[str, Any]]: + return self._inner.read_conditional_formats(workbook, sheet) + + def read_data_validations(self, workbook: Any, sheet: str) -> list[dict[str, Any]]: + return self._inner.read_data_validations(workbook, sheet) + + def read_hyperlinks(self, workbook: Any, sheet: str) -> list[dict[str, Any]]: + return self._inner.read_hyperlinks(workbook, sheet) + + def read_images(self, workbook: Any, sheet: str) -> list[dict[str, Any]]: + return self._inner.read_images(workbook, sheet) + + def read_pivot_tables(self, workbook: Any, sheet: str) -> list[dict[str, Any]]: + return self._inner.read_pivot_tables(workbook, sheet) + + def read_comments(self, workbook: Any, sheet: str) -> list[dict[str, Any]]: + return self._inner.read_comments(workbook, sheet) + + def read_freeze_panes(self, workbook: Any, sheet: str) -> dict[str, Any]: + return self._inner.read_freeze_panes(workbook, sheet) + + +class TestUnsupportedAdapter: + def test_missing_tier4_methods_yield_structured_failures( + self, tmp_path: Path + ) -> None: + bench_dir = _build_bench_dir(tmp_path) + adapter = _Tier3OnlyReader() + + results = run_benchmark(bench_dir, adapters=[adapter], features=TIER4_FEATURES) + + assert len(results.scores) == 3 + for score in results.scores: + read_results = [ + r for r in score.test_results if r.operation.value == "read" + ] + assert len(read_results) == CASE_COUNTS[score.feature] + for result in read_results: + assert result.passed is False + assert "does not implement" in str(result.actual.get("error", "")) + assert result.diagnostics, ( + f"{score.feature}/{result.test_case_id} lacks diagnostics" + ) + assert ( + result.diagnostics[0].category + == DiagnosticCategory.UNSUPPORTED_FEATURE + ) + # Read-only adapter: the write lane is skipped, not scored. + assert score.write_score is None diff --git a/tests/test_zavora_adapter.py b/tests/test_zavora_adapter.py new file mode 100644 index 0000000..90397ba --- /dev/null +++ b/tests/test_zavora_adapter.py @@ -0,0 +1,123 @@ +"""Pure-Python payload tests for the Zavora write adapter.""" + +from __future__ import annotations + +from pathlib import Path + +import pytest + +from excelbench.harness.adapters.zavora_adapter import ZavoraAdapter +from excelbench.harness.external_oracles import ( + ExternalOracleRequest, + ExternalOracleResult, +) +from excelbench.models import CellType, CellValue + + +@pytest.fixture +def zavora() -> ZavoraAdapter: + return ZavoraAdapter() + + +def test_info_declares_write_only_capability(zavora: ZavoraAdapter) -> None: + assert zavora.info.name == "zavora-xlsx" + assert zavora.info.version == "0.1.2" + assert zavora.info.language == "rust" + assert zavora.info.capabilities == {"write"} + assert zavora.can_write() + assert not zavora.can_read() + + +def test_cell_value_and_formula_entries(zavora: ZavoraAdapter) -> None: + workbook = zavora.create_workbook() + zavora.write_cell_value( + workbook, "Data", "A1", CellValue(type=CellType.NUMBER, value=42) + ) + zavora.write_cell_value( + workbook, + "Data", + "B1", + CellValue(type=CellType.FORMULA, value="=A1*2", formula="=A1*2"), + ) + + assert workbook["sheets"] == [{"name": "Data"}] + assert workbook["cells"] == [ + {"sheet": "Data", "cell": "A1", "type": "number", "value": 42}, + { + "sheet": "Data", + "cell": "B1", + "type": "formula", + "formula": "=A1*2", + "value": "=A1*2", + }, + ] + + +def test_table_merge_and_freeze_payloads(zavora: ZavoraAdapter) -> None: + workbook = zavora.create_workbook() + zavora.merge_cells(workbook, "Data", "A1:B1") + zavora.set_freeze_panes( + workbook, "Data", {"freeze": {"mode": "freeze", "y_split": 1}} + ) + zavora.add_table( + workbook, + "Data", + {"table": {"name": "Items", "ref": "A1:B3", "columns": ["Name", "Amount"]}}, + ) + + assert workbook["merges"] == [{"sheet": "Data", "range": "A1:B1"}] + assert workbook["panes"] == [{"sheet": "Data", "mode": "freeze", "y_split": 1}] + assert workbook["tables"] == [ + { + "sheet": "Data", + "range": "A1:B3", + "name": "Items", + "style": None, + "show_header_row": True, + "show_row_stripes": True, + "totals_row": False, + "columns": ["Name", "Amount"], + "autofilter": False, + } + ] + + +def test_save_invokes_write_fixture_request( + zavora: ZavoraAdapter, monkeypatch: pytest.MonkeyPatch, tmp_path: Path +) -> None: + captured: dict[str, object] = {} + + def fake_run( + tool: object, request: object, **kwargs: object + ) -> ExternalOracleResult: + captured["tool"] = tool + captured["request"] = request + captured["kwargs"] = kwargs + return ExternalOracleResult( + tool_name="zavora", + passed=True, + skipped=False, + returncode=0, + stdout='{"ok": true}', + stderr="", + payload={"ok": True}, + ) + + monkeypatch.setattr( + "excelbench.harness.adapters.zavora_adapter.run_external_oracle", fake_run + ) + output_path = tmp_path / "result.xlsx" + workbook = zavora.create_workbook() + zavora.write_cell_value( + workbook, "Data", "A1", CellValue(type=CellType.STRING, value="hello") + ) + + zavora.save_workbook(workbook, output_path) + + request = captured["request"] + assert isinstance(request, ExternalOracleRequest) + assert request.fixture_id == "zavora-adapter" + assert request.operation == "write_fixture" + assert request.output_path == output_path + assert request.payload is workbook + assert captured["kwargs"] == {"timeout_seconds": 300} diff --git a/tools/external-oracles/zavora/.gitignore b/tools/external-oracles/zavora/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/tools/external-oracles/zavora/.gitignore @@ -0,0 +1 @@ +/target diff --git a/tools/external-oracles/zavora/Cargo.toml b/tools/external-oracles/zavora/Cargo.toml new file mode 100644 index 0000000..e774a31 --- /dev/null +++ b/tools/external-oracles/zavora/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "zavora-oracle" +version = "0.1.0" +edition = "2021" +publish = false + +[[bin]] +name = "zavora-oracle" +path = "src/main.rs" + +[dependencies] +serde = { version = "1", features = ["derive"] } +serde_json = "1" +zavora-xlsx = "0.1.2" diff --git a/tools/external-oracles/zavora/src/main.rs b/tools/external-oracles/zavora/src/main.rs new file mode 100644 index 0000000..753fae7 --- /dev/null +++ b/tools/external-oracles/zavora/src/main.rs @@ -0,0 +1,723 @@ +use std::collections::BTreeMap; +use std::fs; +use std::io::{self, Read}; +use std::path::Path; + +use serde::Deserialize; +use serde_json::{json, Map, Value}; +use zavora_xlsx::{ + Align, BorderStyle, CellValue, Chart, ChartType, Format, Table, TableColumn, TableStyle, + Underline, Workbook, +}; + +#[derive(Debug, Deserialize)] +struct OracleRequest { + fixture_id: String, + operation: String, + #[serde(default)] + payload: Value, + input_path: Option, + output_path: Option, +} + +fn main() { + let response = run().unwrap_or_else(|message| failure(None, None, message)); + println!("{response}"); +} + +fn run() -> Result { + let mut input = String::new(); + io::stdin() + .read_to_string(&mut input) + .map_err(|error| format!("read request: {error}"))?; + let request: OracleRequest = + serde_json::from_str(&input).map_err(|error| format!("decode request: {error}"))?; + + match request.operation.as_str() { + "write_fixture" => write_fixture(&request), + "mutate" => mutate(&request), + "calculate" => calculate(&request), + operation => Err(format!("unsupported operation {operation:?}")), + } +} + +fn failure(fixture_id: Option<&str>, operation: Option<&str>, message: String) -> Value { + let mut response = Map::new(); + response.insert("ok".into(), Value::Bool(false)); + response.insert("error".into(), Value::String("zavora_oracle_failed".into())); + response.insert("message".into(), Value::String(message)); + if let Some(fixture_id) = fixture_id { + response.insert("fixture_id".into(), Value::String(fixture_id.into())); + } + if let Some(operation) = operation { + response.insert("operation".into(), Value::String(operation.into())); + } + Value::Object(response) +} + +fn write_fixture(request: &OracleRequest) -> Result { + let output_path = required_path(request.output_path.as_deref(), "write_fixture requires output_path")?; + ensure_supported_payload(&request.payload)?; + + let mut workbook = Workbook::new(); + configure_sheets(&mut workbook, &request.payload)?; + apply_merges(&mut workbook, &request.payload)?; + apply_cells(&mut workbook, &request.payload)?; + apply_formats(&mut workbook, &request.payload)?; + apply_borders(&mut workbook, &request.payload)?; + apply_columns(&mut workbook, &request.payload)?; + apply_row_heights(&mut workbook, &request.payload)?; + apply_hyperlinks(&mut workbook, &request.payload)?; + apply_comments(&mut workbook, &request.payload)?; + apply_panes(&mut workbook, &request.payload)?; + apply_named_ranges(&mut workbook, &request.payload)?; + apply_tables(&mut workbook, &request.payload)?; + apply_charts(&mut workbook, &request.payload)?; + + create_parent(output_path)?; + workbook + .save(output_path) + .map_err(|error| format!("save workbook: {error}"))?; + + Ok(json!({ + "ok": true, + "fixture_id": request.fixture_id, + "operation": request.operation, + "output_path": output_path, + "tool": "zavora-xlsx", + "counts": payload_counts(&request.payload), + })) +} + +fn mutate(request: &OracleRequest) -> Result { + let input_path = required_path(request.input_path.as_deref(), "mutate requires input_path")?; + let output_path = required_path(request.output_path.as_deref(), "mutate requires output_path")?; + let payload = object(&request.payload, "mutate payload")?; + let sheet = required_string(payload, "sheet")?; + let cell = required_string(payload, "cell")?; + let value = payload + .get("value") + .ok_or_else(|| "mutate payload requires value".to_string())?; + let (row, col) = parse_cell(cell)?; + let mut workbook = Workbook::open(input_path).map_err(|error| format!("open workbook: {error}"))?; + write_json_value(workbook.worksheet_by_name(sheet).map_err(|error| error.to_string())?, row, col, value)?; + create_parent(output_path)?; + workbook + .save(output_path) + .map_err(|error| format!("save workbook: {error}"))?; + Ok(json!({ + "ok": true, + "fixture_id": request.fixture_id, + "operation": request.operation, + "output_path": output_path, + "tool": "zavora-xlsx", + })) +} + +fn calculate(request: &OracleRequest) -> Result { + let input_path = required_path(request.input_path.as_deref(), "calculate requires input_path")?; + let output_path = required_path(request.output_path.as_deref(), "calculate requires output_path")?; + let mut workbook = Workbook::open(input_path).map_err(|error| format!("open workbook: {error}"))?; + let formula_cells = collect_formula_cells(&mut workbook)?; + workbook + .recalculate() + .map_err(|error| format!("recalculate workbook: {error}"))?; + let mut values = BTreeMap::new(); + for (sheet_name, row, col) in formula_cells { + let value = workbook + .worksheet_by_name(&sheet_name) + .map_err(|error| error.to_string())? + .read_cell(row, col); + values.insert( + format!("{sheet_name}!{}", cell_name(row, col)), + calculated_value_to_json(&value), + ); + } + create_parent(output_path)?; + workbook + .save(output_path) + .map_err(|error| format!("save workbook: {error}"))?; + Ok(json!({ + "ok": true, + "fixture_id": request.fixture_id, + "operation": request.operation, + "output_path": output_path, + "tool": "zavora-xlsx", + "values": values, + })) +} + +fn collect_formula_cells(workbook: &mut Workbook) -> Result, String> { + let sheet_names: Vec = workbook.sheet_names().into_iter().map(str::to_owned).collect(); + let mut formulas = Vec::new(); + for sheet_name in sheet_names { + let range = { + let sheet = workbook + .worksheet_by_name(&sheet_name) + .map_err(|error| error.to_string())?; + sheet.used_range() + }; + if let Some((first_row, first_col, last_row, last_col)) = range { + let sheet = workbook + .worksheet_by_name(&sheet_name) + .map_err(|error| error.to_string())?; + for row in first_row..=last_row { + for col in first_col..=last_col { + if matches!(sheet.read_cell(row, col), CellValue::Formula { .. }) { + formulas.push((sheet_name.clone(), row, col)); + } + } + } + } + } + Ok(formulas) +} + +fn calculated_value_to_json(value: &CellValue) -> Value { + match value { + CellValue::Formula { cached_value, .. } => calculated_value_to_json(cached_value), + CellValue::Number(number) => json!(number), + CellValue::String(text) | CellValue::Error(text) => json!(text), + CellValue::Bool(boolean) => json!(boolean), + CellValue::DateTime(date_time) => json!(date_time.serial()), + CellValue::Empty | CellValue::RichText(_) => Value::Null, + } +} + +fn configure_sheets(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + let sheets = array(payload, "sheets")?; + if sheets.is_empty() { + return Ok(()); + } + for (index, sheet) in sheets.iter().enumerate() { + let name = required_string(object(sheet, "sheet entry")?, "name")?; + if index == 0 { + workbook + .rename_worksheet(0, name) + .map_err(|error| format!("rename first sheet: {error}"))?; + } else { + workbook + .add_worksheet_with_name(name) + .map_err(|error| format!("add sheet {name:?}: {error}"))?; + } + } + Ok(()) +} + +fn apply_cells(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "cells")? { + let cell = object(entry, "cell entry")?; + let sheet_name = required_string(cell, "sheet")?; + let address = required_string(cell, "cell")?; + let (row, col) = parse_cell(address)?; + let sheet = workbook + .worksheet_by_name(sheet_name) + .map_err(|error| format!("cell {sheet_name}!{address}: {error}"))?; + let cell_type = optional_string(cell, "type").unwrap_or(""); + if cell_type == "blank" { + sheet + .write_blank(row, col, &Format::new()) + .map_err(|error| error.to_string())?; + } else if cell_type == "formula" || cell.get("formula").is_some_and(Value::is_string) { + let formula = optional_string(cell, "formula") + .or_else(|| cell.get("value").and_then(Value::as_str)) + .ok_or_else(|| format!("formula cell {sheet_name}!{address} requires formula or string value"))?; + sheet + .write_formula(row, col, formula) + .map_err(|error| error.to_string())?; + } else if matches!(cell_type, "date" | "datetime" | "error") { + return Err(format!("unsupported cell type {cell_type:?} at {sheet_name}!{address}")); + } else { + let value = cell.get("value").unwrap_or(&Value::Null); + write_json_value(sheet, row, col, value)?; + } + } + Ok(()) +} + +fn write_json_value( + sheet: &mut zavora_xlsx::Worksheet, + row: u32, + col: u16, + value: &Value, +) -> Result<(), String> { + match value { + Value::Null => sheet.write_blank(row, col, &Format::new()), + Value::Bool(boolean) => sheet.write(row, col, *boolean), + Value::Number(number) => sheet.write( + row, + col, + number + .as_f64() + .ok_or_else(|| "cell number cannot be represented as f64".to_string())?, + ), + Value::String(text) => sheet.write(row, col, text.as_str()), + Value::Array(_) | Value::Object(_) => { + return Err("cell value must be number, string, boolean, or null".into()) + } + } + .map(|_| ()) + .map_err(|error| format!("write cell: {error}")) +} + +fn apply_formats(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "formats")? { + let spec = object(entry, "format entry")?; + let sheet_name = required_string(spec, "sheet")?; + let address = required_string(spec, "cell")?; + let (row, col) = parse_cell(address)?; + let format = build_format(spec)?; + workbook + .worksheet_by_name(sheet_name) + .map_err(|error| error.to_string())? + .set_cell_format(row, col, &format) + .map_err(|error| format!("set format {sheet_name}!{address}: {error}"))?; + } + Ok(()) +} + +fn apply_borders(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "borders")? { + let spec = object(entry, "border entry")?; + let sheet_name = required_string(spec, "sheet")?; + let address = required_string(spec, "cell")?; + let border = object( + spec.get("border").ok_or_else(|| "border entry requires border".to_string())?, + "border", + )?; + let mut format = Format::new(); + for (side, apply) in [ + ("top", Format::border_top as fn(Format, BorderStyle) -> Format), + ("bottom", Format::border_bottom as fn(Format, BorderStyle) -> Format), + ("left", Format::border_left as fn(Format, BorderStyle) -> Format), + ("right", Format::border_right as fn(Format, BorderStyle) -> Format), + ] { + if let Some(side_value) = border.get(side) { + let side_spec = object(side_value, "border side")?; + let style = optional_string(side_spec, "style").unwrap_or("none"); + format = apply(format, border_style(style)?); + if let Some(color) = optional_string(side_spec, "color") { + format = match side { + "top" => format.border_top_color(color), + "bottom" => format.border_bottom_color(color), + "left" => format.border_left_color(color), + "right" => format.border_right_color(color), + _ => format, + }; + } + } + } + let (row, col) = parse_cell(address)?; + workbook + .worksheet_by_name(sheet_name) + .map_err(|error| error.to_string())? + .set_cell_format(row, col, &format) + .map_err(|error| format!("set border {sheet_name}!{address}: {error}"))?; + } + Ok(()) +} + +fn build_format(spec: &Map) -> Result { + let mut format = Format::new(); + if optional_bool(spec, "bold") == Some(true) { format = format.bold(); } + if optional_bool(spec, "italic") == Some(true) { format = format.italic(); } + if optional_bool(spec, "strikethrough") == Some(true) { format = format.strikethrough(); } + if let Some(underline) = optional_string(spec, "underline") { + format = format.underline(match underline { + "none" | "" => Underline::None, + "single" => Underline::Single, + "double" => Underline::Double, + _ => return Err(format!("unsupported underline {underline:?}")), + }); + } + if let Some(name) = optional_string(spec, "font_name") { format = format.font_name(name); } + if let Some(size) = optional_number(spec, "font_size") { format = format.font_size(size); } + if let Some(color) = optional_string(spec, "font_color") { format = format.font_color(color); } + if let Some(color) = optional_string(spec, "bg_color") { format = format.background_color(color); } + if let Some(number_format) = optional_string(spec, "number_format") { format = format.num_format(number_format); } + if let Some(horizontal) = optional_string(spec, "h_align") { format = format.align(horizontal_alignment(horizontal)?); } + if let Some(vertical) = optional_string(spec, "v_align") { format = format.align(vertical_alignment(vertical)?); } + if optional_bool(spec, "wrap") == Some(true) { format = format.text_wrap(); } + if let Some(rotation) = optional_number(spec, "rotation") { format = format.rotation(rotation as i16); } + if let Some(indent) = optional_number(spec, "indent") { format = format.indent(indent as u8); } + Ok(format) +} + +fn apply_columns(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "columns")? { + let spec = object(entry, "column entry")?; + let sheet_name = required_string(spec, "sheet")?; + let start = required_string(spec, "start")?; + let end = required_string(spec, "end")?; + let width = required_number(spec, "width")?; + let start_col = parse_column(start)?; + let end_col = parse_column(end)?; + if start_col > end_col { return Err(format!("invalid column range {start}:{end}")); } + let sheet = workbook.worksheet_by_name(sheet_name).map_err(|error| error.to_string())?; + for col in start_col..=end_col { + sheet.set_column_width(col, width).map_err(|error| error.to_string())?; + } + } + Ok(()) +} + +fn apply_row_heights(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "row_heights")? { + let spec = object(entry, "row height entry")?; + let sheet_name = required_string(spec, "sheet")?; + let row = required_u32(spec, "row")?.checked_sub(1).ok_or_else(|| "row must be positive".to_string())?; + let height = required_number(spec, "height")?; + workbook.worksheet_by_name(sheet_name).map_err(|error| error.to_string())? + .set_row_height(row, height).map_err(|error| error.to_string())?; + } + Ok(()) +} + +fn apply_merges(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "merges")? { + let spec = object(entry, "merge entry")?; + let sheet_name = required_string(spec, "sheet")?; + let range = required_string(spec, "range")?; + let (first_row, first_col, last_row, last_col) = parse_range(range)?; + workbook.worksheet_by_name(sheet_name).map_err(|error| error.to_string())? + .merge_range(first_row, first_col, last_row, last_col, "", &Format::new()) + .map_err(|error| format!("merge {sheet_name}!{range}: {error}"))?; + } + Ok(()) +} + +fn apply_hyperlinks(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "hyperlinks")? { + let spec = object(entry, "hyperlink entry")?; + if spec.get("tooltip").is_some_and(|value| !value.is_null() && value != "") { + return Err("unsupported hyperlink part: tooltip".into()); + } + let sheet_name = required_string(spec, "sheet")?; + let address = required_string(spec, "cell")?; + let target = required_string(spec, "target")?; + let display = optional_string(spec, "display").unwrap_or(""); + let (row, col) = parse_cell(address)?; + let sheet = workbook.worksheet_by_name(sheet_name).map_err(|error| error.to_string())?; + if optional_bool(spec, "internal") == Some(true) { + sheet.write_internal_link(row, col, target, display).map_err(|error| error.to_string())?; + } else { + sheet.write_url(row, col, target, display).map_err(|error| error.to_string())?; + } + } + Ok(()) +} + +fn apply_comments(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "comments")? { + let spec = object(entry, "comment entry")?; + let sheet_name = required_string(spec, "sheet")?; + let address = required_string(spec, "cell")?; + let text = required_string(spec, "text")?; + let author = optional_string(spec, "author").unwrap_or("Author"); + let (row, col) = parse_cell(address)?; + workbook.worksheet_by_name(sheet_name).map_err(|error| error.to_string())? + .add_comment_with_author(row, col, text, author); + } + Ok(()) +} + +fn apply_panes(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "panes")? { + let spec = object(entry, "pane entry")?; + if let Some(mode) = optional_string(spec, "mode") { + if mode != "" && mode != "freeze" { return Err(format!("unsupported pane mode {mode:?}")); } + } + if spec.get("top_left_cell").is_some_and(|value| !value.is_null() && value != "") { + return Err("unsupported pane part: top_left_cell".into()); + } + let sheet_name = required_string(spec, "sheet")?; + let row = optional_u32(spec, "y_split").unwrap_or(0); + let col = optional_u16(spec, "x_split").unwrap_or(0); + workbook.worksheet_by_name(sheet_name).map_err(|error| error.to_string())? + .set_freeze_panes(row, col).map_err(|error| error.to_string())?; + } + Ok(()) +} + +fn apply_named_ranges(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "named_ranges")? { + let spec = object(entry, "named range entry")?; + let name = required_string(spec, "name")?; + let formula = required_string(spec, "refers_to")?; + if optional_string(spec, "scope") == Some("sheet") { + let sheet_name = required_string(spec, "sheet")?; + let sheet_index = workbook.sheet_names().iter().position(|candidate| *candidate == sheet_name) + .ok_or_else(|| format!("named range sheet {sheet_name:?} does not exist"))?; + workbook.define_name_scoped(name, formula, sheet_index); + } else { + workbook.define_name(name, formula); + } + } + Ok(()) +} + +fn apply_tables(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "tables")? { + let spec = object(entry, "table entry")?; + if optional_bool(spec, "show_header_row") == Some(false) { + return Err("unsupported table part: show_header_row=false".into()); + } + if optional_bool(spec, "show_row_stripes") == Some(false) { + return Err("unsupported table part: show_row_stripes=false".into()); + } + let sheet_name = required_string(spec, "sheet")?; + let range = required_string(spec, "range")?; + let (first_row, first_col, last_row, last_col) = parse_range(range)?; + let mut table = Table::new(); + if let Some(name) = optional_string(spec, "name") { table.set_name(name); } + if let Some(style) = optional_string(spec, "style") { table.set_style(parse_table_style(style)?); } + table.set_total_row(optional_bool(spec, "totals_row").unwrap_or(false)); + table.set_autofilter(optional_bool(spec, "autofilter").unwrap_or(true)); + let columns: Result, String> = object_array(spec, "columns")?.iter() + .map(|value| value.as_str().map(TableColumn::new).ok_or_else(|| "table columns must be strings".to_string())) + .collect(); + table.set_columns(&columns?); + workbook.worksheet_by_name(sheet_name).map_err(|error| error.to_string())? + .add_table(first_row, first_col, last_row, last_col, &table) + .map_err(|error| format!("add table {sheet_name}!{range}: {error}"))?; + } + Ok(()) +} + +fn apply_charts(workbook: &mut Workbook, payload: &Value) -> Result<(), String> { + for entry in array(payload, "charts")? { + let spec = object(entry, "chart entry")?; + if spec.get("vary_colors").is_some_and(|value| !value.is_null()) { + return Err("unsupported chart part: vary_colors".into()); + } + let sheet_name = required_string(spec, "sheet")?; + let address = required_string(spec, "cell")?; + let chart_type = parse_chart_type(required_string(spec, "type")?)?; + let (row, col) = parse_cell(address)?; + let mut chart = Chart::new(chart_type); + if let Some(title) = optional_string(spec, "title") { chart.set_title(title); } + if let Some(width) = optional_u32(spec, "width") { chart.set_width(width); } + if let Some(height) = optional_u32(spec, "height") { chart.set_height(height); } + if let Some(alt_text) = optional_string(spec, "alt_text") { chart.set_alt_text(optional_string(spec, "name").unwrap_or("Chart"), alt_text); } + let series = object_array(spec, "series")?; + if series.is_empty() { + let values = required_string(spec, "values")?; + let item = chart.add_series(); + item.set_values(values); + if let Some(categories) = optional_string(spec, "categories") { item.set_categories(categories); } + if let Some(name) = optional_string(spec, "name") { item.set_name(name); } + item.set_data_labels(optional_bool(spec, "show_values").unwrap_or(false)); + } else { + for series_spec in series { + let series_object = object(series_spec, "chart series")?; + let item = chart.add_series(); + item.set_values(required_string(series_object, "values")?); + if let Some(categories) = optional_string(series_object, "categories") { item.set_categories(categories); } + if let Some(name) = optional_string(series_object, "name") { item.set_name(name); } + if let Some(color) = optional_string(series_object, "fill_color") { item.set_color(color); } + item.set_data_labels(optional_bool(spec, "show_values").unwrap_or(false)); + for point in object_array(series_object, "data_points")? { + let point = object(point, "chart data point")?; + if let Some(color) = optional_string(point, "fill_color") { + item.set_point_color(required_u32(point, "index")? as usize, color); + } + } + } + } + workbook.worksheet_by_name(sheet_name).map_err(|error| error.to_string())? + .insert_chart(row, col, &chart).map_err(|error| error.to_string())?; + } + Ok(()) +} + +fn ensure_supported_payload(payload: &Value) -> Result<(), String> { + let root = object(payload, "write payload")?; + for part in ["validations", "conditional_formats", "pivots", "slicers", "pictures"] { + if !object_array(root, part)?.is_empty() { + return Err(format!("unsupported payload part: {part}")); + } + } + Ok(()) +} + +fn payload_counts(payload: &Value) -> Value { + let mut counts = Map::new(); + for name in [ + "sheets", "cells", "formats", "borders", "merges", "row_heights", "validations", + "hyperlinks", "comments", "panes", "named_ranges", "tables", "conditional_formats", + "charts", "pivots", "slicers", "pictures", + ] { + let count = payload.get(name).and_then(Value::as_array).map_or(0, Vec::len); + counts.insert(name.into(), json!(count)); + } + Value::Object(counts) +} + +fn object<'a>(value: &'a Value, context: &str) -> Result<&'a Map, String> { + value.as_object().ok_or_else(|| format!("{context} must be an object")) +} + +fn array<'a>(value: &'a Value, name: &str) -> Result, String> { + match value.get(name) { + None | Some(Value::Null) => Ok(Vec::new()), + Some(Value::Array(values)) => Ok(values.iter().collect()), + Some(_) => Err(format!("{name} must be an array")), + } +} + +fn object_array<'a>( + object: &'a Map, + name: &str, +) -> Result, String> { + match object.get(name) { + None | Some(Value::Null) => Ok(Vec::new()), + Some(Value::Array(values)) => Ok(values.iter().collect()), + Some(_) => Err(format!("{name} must be an array")), + } +} + +fn required_string<'a>(object: &'a Map, name: &str) -> Result<&'a str, String> { + optional_string(object, name).filter(|value| !value.is_empty()) + .ok_or_else(|| format!("{name} is required")) +} + +fn optional_string<'a>(object: &'a Map, name: &str) -> Option<&'a str> { + object.get(name).and_then(Value::as_str) +} + +fn required_number(object: &Map, name: &str) -> Result { + optional_number(object, name).ok_or_else(|| format!("{name} must be a number")) +} + +fn optional_number(object: &Map, name: &str) -> Option { + object.get(name).and_then(Value::as_f64) +} + +fn required_u32(object: &Map, name: &str) -> Result { + optional_u32(object, name).ok_or_else(|| format!("{name} must be a positive integer")) +} + +fn optional_u32(object: &Map, name: &str) -> Option { + object.get(name).and_then(Value::as_u64).and_then(|value| u32::try_from(value).ok()) +} + +fn optional_u16(object: &Map, name: &str) -> Option { + object.get(name).and_then(Value::as_u64).and_then(|value| u16::try_from(value).ok()) +} + +fn optional_bool(object: &Map, name: &str) -> Option { + object.get(name).and_then(Value::as_bool) +} + +fn required_path<'a>(path: Option<&'a str>, message: &str) -> Result<&'a str, String> { + path.filter(|value| !value.is_empty()).ok_or_else(|| message.to_string()) +} + +fn create_parent(path: &str) -> Result<(), String> { + let parent = Path::new(path).parent().unwrap_or_else(|| Path::new(".")); + fs::create_dir_all(parent).map_err(|error| format!("create output directory: {error}")) +} + +fn parse_cell(value: &str) -> Result<(u32, u16), String> { + let split = value.find(|character: char| character.is_ascii_digit()) + .ok_or_else(|| format!("invalid cell reference {value:?}"))?; + let (column, row) = value.split_at(split); + if column.is_empty() || row.is_empty() || !column.chars().all(|character| character.is_ascii_alphabetic()) { + return Err(format!("invalid cell reference {value:?}")); + } + let row = row.parse::().map_err(|_| format!("invalid cell reference {value:?}"))? + .checked_sub(1).ok_or_else(|| format!("invalid cell reference {value:?}"))?; + Ok((row, parse_column(column)?)) +} + +fn parse_column(value: &str) -> Result { + if value.is_empty() || !value.chars().all(|character| character.is_ascii_alphabetic()) { + return Err(format!("invalid column {value:?}")); + } + let mut result = 0u32; + for character in value.bytes() { + result = result.checked_mul(26).and_then(|current| current.checked_add(u32::from(character.to_ascii_uppercase() - b'A' + 1))) + .ok_or_else(|| format!("invalid column {value:?}"))?; + } + u16::try_from(result.checked_sub(1).ok_or_else(|| format!("invalid column {value:?}"))?) + .map_err(|_| format!("column out of range {value:?}")) +} + +fn parse_range(value: &str) -> Result<(u32, u16, u32, u16), String> { + let (start, end) = value.split_once(':').ok_or_else(|| format!("invalid range {value:?}"))?; + let (first_row, first_col) = parse_cell(start)?; + let (last_row, last_col) = parse_cell(end)?; + if first_row > last_row || first_col > last_col { return Err(format!("invalid range {value:?}")); } + Ok((first_row, first_col, last_row, last_col)) +} + +fn cell_name(row: u32, col: u16) -> String { + let mut column = u32::from(col) + 1; + let mut letters = String::new(); + while column > 0 { + let remainder = (column - 1) % 26; + letters.insert(0, char::from(b'A' + u8::try_from(remainder).unwrap_or(0))); + column = (column - 1) / 26; + } + format!("{}{}", letters, row + 1) +} + +fn border_style(value: &str) -> Result { + match value { + "" | "none" => Ok(BorderStyle::None), + "thin" => Ok(BorderStyle::Thin), + "medium" => Ok(BorderStyle::Medium), + "thick" => Ok(BorderStyle::Thick), + "dashed" => Ok(BorderStyle::Dashed), + "dotted" => Ok(BorderStyle::Dotted), + "double" => Ok(BorderStyle::Double), + _ => Err(format!("unsupported border style {value:?}")), + } +} + +fn horizontal_alignment(value: &str) -> Result { + match value { + "" | "general" | "left" => Ok(Align::Left), + "center" => Ok(Align::Center), + "right" => Ok(Align::Right), + "fill" => Ok(Align::Fill), + "justify" => Ok(Align::Justify), + _ => Err(format!("unsupported horizontal alignment {value:?}")), + } +} + +fn vertical_alignment(value: &str) -> Result { + match value { + "" | "bottom" => Ok(Align::Bottom), + "top" => Ok(Align::Top), + "center" => Ok(Align::VerticalCenter), + _ => Err(format!("unsupported vertical alignment {value:?}")), + } +} + +fn parse_table_style(value: &str) -> Result { + for (prefix, build) in [ + ("TableStyleLight", TableStyle::Light as fn(u8) -> TableStyle), + ("TableStyleMedium", TableStyle::Medium as fn(u8) -> TableStyle), + ("TableStyleDark", TableStyle::Dark as fn(u8) -> TableStyle), + ] { + if let Some(number) = value.strip_prefix(prefix) { + return number.parse::().map(build).map_err(|_| format!("unsupported table style {value:?}")); + } + } + Err(format!("unsupported table style {value:?}")) +} + +fn parse_chart_type(value: &str) -> Result { + match value { + "area" => Ok(ChartType::Area), + "bar" => Ok(ChartType::Bar), + "col" | "column" => Ok(ChartType::Column), + "line" => Ok(ChartType::Line), + "pie" => Ok(ChartType::Pie), + "doughnut" => Ok(ChartType::Doughnut), + "scatter" => Ok(ChartType::Scatter), + "bubble" => Ok(ChartType::Bubble), + _ => Err(format!("unsupported chart type {value:?}")), + } +} diff --git a/uv.lock b/uv.lock index 4f98766..cd1b5ef 100644 --- a/uv.lock +++ b/uv.lock @@ -33,7 +33,7 @@ name = "appscript" version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "lxml", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "lxml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ca/52/2fa70edfd98f0058219ecc2e365a3ba7aabd42db14ff9d7f44bbdcc5400d/appscript-1.4.0.tar.gz", hash = "sha256:b2c6fc770bf822ea45529c7084bc0ee340e67ab260016b01d28e0449ec8723be", size = 295279, upload-time = "2025-10-08T07:56:39.126Z" } wheels = [ @@ -47,6 +47,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/dd/e3/03dc0f97eab839f72061342d69bd34424e89876ce4026509aab3d74d4f23/appscript-1.4.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:5efce3302c00674b769b79938cc5f66f7791ef45c6419e850a5f1c8f9fcefcc1", size = 85610, upload-time = "2025-10-08T07:56:38.103Z" }, ] +[[package]] +name = "aspose-cells-foss" +version = "26.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "olefile" }, + { name = "pycryptodome" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e8/38/c4704d0ee0fcddfe69bf1c6b2d1eb8d0c51cebd4cd5e18ac92361f414b49/aspose_cells_foss-26.7.0.tar.gz", hash = "sha256:006dfe6d9dbdbd6d626f3ecc65f800ed838c28e4560178aaaf758482416a7350", size = 292477, upload-time = "2026-07-24T13:53:31.802Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/28/aa193a491df0325a86b99810e4ec4658c50e551eab2cbaad1632074dbddd/aspose_cells_foss-26.7.0-py3-none-any.whl", hash = "sha256:e903641b54ddcbaa1956a6e35e14b90b1d08e96675011f05aafa219d0ef1c720", size = 333188, upload-time = "2026-07-24T13:53:29.97Z" }, +] + [[package]] name = "babel" version = "2.18.0" @@ -398,6 +411,9 @@ dependencies = [ ] [package.optional-dependencies] +aspose = [ + { name = "aspose-cells-foss" }, +] dev = [ { name = "mypy" }, { name = "pytest" }, @@ -415,6 +431,7 @@ rust = [ [package.metadata] requires-dist = [ + { name = "aspose-cells-foss", marker = "extra == 'aspose'", specifier = ">=26.7" }, { name = "fastexcel", specifier = ">=0.7.0" }, { name = "matplotlib", specifier = ">=3.7.0" }, { name = "mkdocs-material", marker = "extra == 'docs'", specifier = ">=9.5" }, @@ -443,7 +460,7 @@ requires-dist = [ { name = "xlwings", specifier = ">=0.30.0" }, { name = "xlwt", specifier = ">=1.3.0" }, ] -provides-extras = ["dev", "rust", "docs"] +provides-extras = ["dev", "rust", "docs", "aspose"] [[package]] name = "fastexcel" @@ -1146,6 +1163,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/de/e5/b7d20451657664b07986c2f6e3be564433f5dcaf3482d68eaecd79afaf03/numpy-2.4.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0", size = 12502577, upload-time = "2026-01-31T23:13:07.08Z" }, ] +[[package]] +name = "olefile" +version = "0.47" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/69/1b/077b508e3e500e1629d366249c3ccb32f95e50258b231705c09e3c7a4366/olefile-0.47.zip", hash = "sha256:599383381a0bf3dfbd932ca0ca6515acd174ed48870cbf7fee123d698c192c1c", size = 112240, upload-time = "2023-12-01T16:22:53.025Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/d3/b64c356a907242d719fc668b71befd73324e47ab46c8ebbbede252c154b2/olefile-0.47-py2.py3-none-any.whl", hash = "sha256:543c7da2a7adadf21214938bb79c83ea12b473a4b6ee4ad4bf854e7715e13d1f", size = 114565, upload-time = "2023-12-01T16:22:51.518Z" }, +] + [[package]] name = "openpyxl" version = "3.1.5" @@ -1405,6 +1431,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, ] +[[package]] +name = "pycryptodome" +version = "3.23.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276, upload-time = "2025-05-17T17:21:45.242Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152, upload-time = "2025-05-17T17:20:20.833Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348, upload-time = "2025-05-17T17:20:23.171Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033, upload-time = "2025-05-17T17:20:25.424Z" }, + { url = "https://files.pythonhosted.org/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142, upload-time = "2025-05-17T17:20:27.808Z" }, + { url = "https://files.pythonhosted.org/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384, upload-time = "2025-05-17T17:20:30.765Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237, upload-time = "2025-05-17T17:20:33.736Z" }, + { url = "https://files.pythonhosted.org/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898, upload-time = "2025-05-17T17:20:36.086Z" }, + { url = "https://files.pythonhosted.org/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197, upload-time = "2025-05-17T17:20:38.414Z" }, + { url = "https://files.pythonhosted.org/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600, upload-time = "2025-05-17T17:20:40.688Z" }, + { url = "https://files.pythonhosted.org/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740, upload-time = "2025-05-17T17:20:42.413Z" }, + { url = "https://files.pythonhosted.org/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685, upload-time = "2025-05-17T17:20:44.388Z" }, + { url = "https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627, upload-time = "2025-05-17T17:20:47.139Z" }, + { url = "https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362, upload-time = "2025-05-17T17:20:50.392Z" }, + { url = "https://files.pythonhosted.org/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625, upload-time = "2025-05-17T17:20:52.866Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954, upload-time = "2025-05-17T17:20:55.027Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534, upload-time = "2025-05-17T17:20:57.279Z" }, + { url = "https://files.pythonhosted.org/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853, upload-time = "2025-05-17T17:20:59.322Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465, upload-time = "2025-05-17T17:21:03.83Z" }, + { url = "https://files.pythonhosted.org/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414, upload-time = "2025-05-17T17:21:06.72Z" }, + { url = "https://files.pythonhosted.org/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484, upload-time = "2025-05-17T17:21:08.535Z" }, + { url = "https://files.pythonhosted.org/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636, upload-time = "2025-05-17T17:21:10.393Z" }, + { url = "https://files.pythonhosted.org/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675, upload-time = "2025-05-17T17:21:13.146Z" }, +] + [[package]] name = "pydantic" version = "2.12.5" From f9948d7df1f4a1a5a90292282c0f9ac6c948a0bf Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Mon, 7 Sep 2026 22:48:57 -0700 Subject: [PATCH 02/11] docs(results): add competitor snapshot heatmap and README link --- README.md | 1 + results-2026-09-08/xlsx/heatmap.png | Bin 0 -> 166502 bytes results-2026-09-08/xlsx/heatmap.svg | 4174 +++++++++++++++++++++++++++ 3 files changed, 4175 insertions(+) create mode 100644 results-2026-09-08/xlsx/heatmap.png create mode 100644 results-2026-09-08/xlsx/heatmap.svg diff --git a/README.md b/README.md index 11cb22d..91215bd 100644 --- a/README.md +++ b/README.md @@ -298,6 +298,7 @@ None currently queued. Tier 4 (charts anchoring, print settings, protection) shi ## Detailed Results - **[Competitor snapshot fidelity](results-2026-09-08/xlsx/README.md)** -- 22 features x 14 Python adapters, WolfXL 2.1.0 + aspose-cells-foss +- **[Competitor snapshot heatmap](results-2026-09-08/xlsx/heatmap.png)** ([SVG](results-2026-09-08/xlsx/heatmap.svg)) -- 22x14 visual score matrix - **[Competitor snapshot mutation](results-2026-09-08/mutation/README.md)** -- template mutation: wall time, RSS, preservation - **[Competitor snapshot calc](results-2026-09-08/calc/README.md)** -- 133-formula financial DAG vs LibreOffice oracle - **[Competitor snapshot zavora cross-language](results-2026-09-08/cross-language/README.md)** -- zavora-xlsx 0.1.2 Rust writer context diff --git a/results-2026-09-08/xlsx/heatmap.png b/results-2026-09-08/xlsx/heatmap.png new file mode 100644 index 0000000000000000000000000000000000000000..4f7690e7de8e6e97fee450303f50912c8567f406 GIT binary patch literal 166502 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�#5y!~7IYgUYSiFJB>y1E~_$ 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

!;U@23|g_jTT1wL`X{*WrIKw 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𝔷8Iuvj8HJIbGB)fJX&aX;}! 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 literal 0 HcmV?d00001 diff --git a/results-2026-09-08/xlsx/heatmap.svg b/results-2026-09-08/xlsx/heatmap.svg new file mode 100644 index 0000000..7f94e65 --- /dev/null +++ b/results-2026-09-08/xlsx/heatmap.svg @@ -0,0 +1,4174 @@ + + + + + + + + 2026-09-07T22:48:38.385380 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 86eec8ad4982cb73713e7e83d117657497f42929 Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Mon, 7 Sep 2026 23:25:27 -0700 Subject: [PATCH 03/11] fix(ci): satisfy mypy strict gates and skip aspose tests without the extra - base.unsupported_operation now annotated NoReturn (it always raises); downstream use is unreachable and mypy-clean without local asserts - restore pyumya mypy override clobbered by the aspose override entry; add aspose/aspose.* overrides for the untyped installed package - type the wolfxl adapter pivot/table fallbacks, calc suite status/reason locals, aspose merged-ranges return - guard optional module imports in modifiable.py with the registry pattern - pytest.importorskip for aspose-cells-foss when the extra is absent Verification: ruff clean; mypy 0 issues in 149 files; pytest 1235 passed, 79 skipped, 6 xfailed. --- fixtures/excel/tier4_manifest_fragment.json | 181 ++++++++++++++++++ fixtures/mutation/manifest.json | 2 +- .../mutation/template_corporate_model.xlsx | Bin 15043 -> 15043 bytes pyproject.toml | 4 + .../adapters/aspose_cells_foss_adapter.py | 3 +- src/excelbench/harness/adapters/base.py | 9 +- .../harness/adapters/wolfxl_adapter.py | 6 +- src/excelbench/harness/calc.py | 8 +- src/excelbench/modifiable.py | 22 ++- tests/test_aspose_cells_foss_adapter.py | 2 + 10 files changed, 222 insertions(+), 15 deletions(-) create mode 100644 fixtures/excel/tier4_manifest_fragment.json diff --git a/fixtures/excel/tier4_manifest_fragment.json b/fixtures/excel/tier4_manifest_fragment.json new file mode 100644 index 0000000..c26f126 --- /dev/null +++ b/fixtures/excel/tier4_manifest_fragment.json @@ -0,0 +1,181 @@ +{ + "generated_at": "2026-09-08T05:26:38.636308+00:00", + "excel_version": "none", + "generator_version": "0.1.0", + "generator": "openpyxl-structural", + "file_format": "xlsx", + "files": [ + { + "path": "tier4/20_sheet_protection.xlsx", + "feature": "sheet_protection", + "tier": 4, + "file_format": "xlsx", + "test_cases": [ + { + "id": "prot_basic", + "label": "Protection: basic (OOXML defaults)", + "row": 2, + "sheet": "sheet_protection_basic", + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "importance": "basic" + }, + { + "id": "prot_password", + "label": "Protection: with password hash", + "row": 2, + "sheet": "sheet_protection_password", + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "importance": "basic" + }, + { + "id": "prot_granular", + "label": "Protection: granular attribute flags", + "row": 2, + "sheet": "sheet_protection_granular", + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "importance": "edge" + } + ] + }, + { + "path": "tier4/21_page_setup.xlsx", + "feature": "page_setup", + "tier": 4, + "file_format": "xlsx", + "test_cases": [ + { + "id": "page_setup_landscape", + "label": "Page setup: landscape + fit-to-width", + "row": 2, + "sheet": "page_setup_landscape", + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "importance": "basic" + }, + { + "id": "page_setup_scale", + "label": "Page setup: portrait at 75% scale", + "row": 2, + "sheet": "page_setup_scale", + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "importance": "basic" + }, + { + "id": "page_setup_titles", + "label": "Page setup: print titles + header/footer", + "row": 2, + "sheet": "page_setup_titles", + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "importance": "edge" + } + ] + }, + { + "path": "tier4/22_chart_anchor.xlsx", + "feature": "chart_anchor", + "tier": 4, + "file_format": "xlsx", + "test_cases": [ + { + "id": "chart_bar", + "label": "Chart: bar with twoCell anchor", + "row": 2, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "importance": "basic" + }, + { + "id": "chart_line", + "label": "Chart: line with twoCell anchor", + "row": 2, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "importance": "edge" + } + ] + } + ] +} diff --git a/fixtures/mutation/manifest.json b/fixtures/mutation/manifest.json index ce3c212..45287af 100644 --- a/fixtures/mutation/manifest.json +++ b/fixtures/mutation/manifest.json @@ -6,7 +6,7 @@ "customXml/item1.xml": "e9add2e6b47913324315bf91125bcce244eee364ba11ec00803e226674fe35b1", "customXml/itemProps1.xml": "de62706849294a697ecf047953b54c0183a264d5226ef3f43cf3ce47d2ee3662", "docProps/app.xml": "209fca6b00afe72a5029754b94be5953d8f16d96f67130325566b9366ad4ccc5", - "docProps/core.xml": "b9e8524ed1f1740bd77a8ba5d3ccc1122cfd6e5315775cee7f928e88807f42da", + "docProps/core.xml": "e4fb90e29af41c5d404c9b110cd1be7184f46a2767a2aea64160b29771a25a21", "xl/_rels/workbook.xml.rels": "9f80b92319d8b9c20f25d718624b941fcbb42403a9f86fe137722889b35d4b87", "xl/charts/chart1.xml": "54c98567bbe1b8340e8e0cd4dac37b07ed37a4fedf59832db1ef04499daf0eaf", "xl/charts/chart2.xml": "2c793da99c3bcf4e2f96daad7ae96f14be96703e1c5cb243255767e844d29f59", diff --git a/fixtures/mutation/template_corporate_model.xlsx b/fixtures/mutation/template_corporate_model.xlsx index 91c4bc3f47c84150cb672e75590b6c99b5dc5144..a5cbfa50fa973eac9ec2dd87bc2248ec9d888960 100644 GIT binary patch delta 291 zcmV+;0o?w>b;EVANd^Qr6V&39O$Hx-QA@)x5XZlYuS74E(mLy>YW^N&}rq)U*kCFy|#%s0U-G}cIOe?^D4lVW+ zpvVhg%{vt7hw|!3QW~L7$ zdxh~;FoI4FH|#R`Wp)41KC-6dWtH(Fo|bcw&fDzz!|y6=2W|G|9~j?d{I=zlDA$6o pzZqWyn;L%oi{=whO9KQH0001!Q8pH{fCrc^1UD1Z;b;EVANd^S|z`10TO$Hx-!Ait15Qbkxa&IT?xx{Q2e^NUfYugU4q-IP_#NTurv?gHUe6_C!tq1hq#iLmm@- zY;Ff{CB>`Xfs^V(?hs1OE3imXOOh}HGq(^~Q)?xZM@fS};+0^lePB(=%PQkVJT2!Uo%h-Gm)}{~4%%$Z1sLCE{HEn=alIBr p^~3li*wpanUo>A(O9KQH0001!Q8pH{fCrc^1pdIeWV0MLrv$o*ijn{T diff --git a/pyproject.toml b/pyproject.toml index 3606611..ad38bfb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -124,8 +124,12 @@ module = [ "plotly", "plotly.*", "numpy.*", + "aspose", + "aspose.*", "aspose.cells_foss", "aspose.cells_foss.*", + "pyumya", + "pyumya.*", ] ignore_missing_imports = true diff --git a/src/excelbench/harness/adapters/aspose_cells_foss_adapter.py b/src/excelbench/harness/adapters/aspose_cells_foss_adapter.py index b090e26..547bffb 100644 --- a/src/excelbench/harness/adapters/aspose_cells_foss_adapter.py +++ b/src/excelbench/harness/adapters/aspose_cells_foss_adapter.py @@ -291,7 +291,8 @@ def read_column_width(self, workbook: Any, sheet: str, column: str) -> float | N def read_merged_ranges(self, workbook: Any, sheet: str) -> list[str]: """Read merged A1 ranges.""" - return workbook.get_worksheet(sheet).cells.get_merged_cells() + merged: list[str] = workbook.get_worksheet(sheet).cells.get_merged_cells() + return merged def read_conditional_formats(self, workbook: Any, sheet: str) -> list[JSONDict]: """Read conditional-format rules exposed by the FOSS API.""" diff --git a/src/excelbench/harness/adapters/base.py b/src/excelbench/harness/adapters/base.py index 9ec7889..182308d 100644 --- a/src/excelbench/harness/adapters/base.py +++ b/src/excelbench/harness/adapters/base.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from pathlib import Path -from typing import Any +from typing import Any, NoReturn from excelbench.models import ( BorderInfo, @@ -95,8 +95,11 @@ def supports_read_path(self, path: Path) -> bool: suffix = path.suffix.lower() return suffix in self.supported_read_extensions - def unsupported_operation(self, operation: str, reason: str) -> None: - """Raise a structured unsupported-feature exception for adapter methods.""" + def unsupported_operation(self, operation: str, reason: str) -> NoReturn: + """Raise a structured unsupported-feature exception for adapter methods. + + Never returns: the raised error is the structured unsupported signal. + """ raise UnsupportedAdapterOperationError( adapter=self.name, operation=operation, reason=reason ) diff --git a/src/excelbench/harness/adapters/wolfxl_adapter.py b/src/excelbench/harness/adapters/wolfxl_adapter.py index da8fe01..c7b9b73 100644 --- a/src/excelbench/harness/adapters/wolfxl_adapter.py +++ b/src/excelbench/harness/adapters/wolfxl_adapter.py @@ -472,6 +472,7 @@ def read_pivot_tables(self, workbook: Any, sheet: str) -> list[JSONDict]: worksheet_source = getattr(cache_source, "worksheetSource", None) source_ref = getattr(worksheet_source, "ref", None) source_sheet = getattr(worksheet_source, "sheet", None) + source_range: str | None if source_sheet and source_ref: source_range = f"{source_sheet}!{source_ref}" else: @@ -589,7 +590,10 @@ def read_tables(self, workbook: Any, sheet: str) -> list[JSONDict]: if not columns: from wolfxl.utils.cell import range_boundaries - min_col, min_row, max_col, _ = range_boundaries(str(table.ref)) + boundaries = range_boundaries(str(table.ref)) + min_col = int(boundaries[0] or 0) + min_row = int(boundaries[1] or 0) + max_col = int(boundaries[2] or 0) columns = [ "" if worksheet.cell(row=min_row, column=column).value is None diff --git a/src/excelbench/harness/calc.py b/src/excelbench/harness/calc.py index 6992f8b..290a810 100644 --- a/src/excelbench/harness/calc.py +++ b/src/excelbench/harness/calc.py @@ -335,7 +335,7 @@ def values_match(expected: Any, actual: Any) -> bool: ) if isinstance(expected, (int, float)) and isinstance(actual, (int, float)): return math.isclose(float(expected), float(actual), abs_tol=1e-6, rel_tol=1e-9) - return expected == actual + return bool(expected == actual) def run_calc_suite( @@ -367,6 +367,7 @@ def run_calc_suite( values = {} matched, mismatches = _compare_expected_values(expected_cells, values) total = len(expected_cells) + reason: str | None if engine_result["status"] == "passed" and matched < total: # An engine that runs but produces wrong or missing values is a # failed calculation run, not a pass. @@ -379,7 +380,7 @@ def run_calc_suite( f"{missing} missing, {wrong} wrong)" ) else: - status = engine_result["status"] + status = str(engine_result["status"]) reason = engine_result.get("reason") engine_results[engine.name] = { "status": status, @@ -431,7 +432,8 @@ def _load_expected(expected: dict[str, Any] | Path) -> dict[str, Any]: expected_path = ( expected / "expected_values.json" if expected.is_dir() else expected ) - return json.loads(expected_path.read_text()) + loaded: dict[str, Any] = json.loads(expected_path.read_text()) + return loaded return expected diff --git a/src/excelbench/modifiable.py b/src/excelbench/modifiable.py index 590ed6e..da78967 100644 --- a/src/excelbench/modifiable.py +++ b/src/excelbench/modifiable.py @@ -12,20 +12,30 @@ run_external_oracle, ) +_openpyxl: Any = None +_wolfxl: Any = None +_aspose_cells_foss: Any = None + try: - import openpyxl as _openpyxl + import openpyxl + + _openpyxl = openpyxl except ImportError: # pragma: no cover - optional dependency guard - _openpyxl = None + pass try: - import wolfxl as _wolfxl + import wolfxl + + _wolfxl = wolfxl except ImportError: # pragma: no cover - optional dependency guard - _wolfxl = None + pass try: - import aspose.cells_foss as _aspose_cells_foss + import aspose.cells_foss + + _aspose_cells_foss = aspose.cells_foss except ImportError: # pragma: no cover - optional dependency guard - _aspose_cells_foss = None + pass Mutation = dict[str, Any] _REPO_ROOT = Path(__file__).resolve().parents[2] diff --git a/tests/test_aspose_cells_foss_adapter.py b/tests/test_aspose_cells_foss_adapter.py index a0d61a9..8b5e7bb 100644 --- a/tests/test_aspose_cells_foss_adapter.py +++ b/tests/test_aspose_cells_foss_adapter.py @@ -17,6 +17,8 @@ CellValue, ) +pytest.importorskip("aspose.cells_foss", reason="optional 'aspose' extra not installed") + @pytest.fixture def adapter() -> AsposeCellsFossAdapter: From 649b75c10a3220dd24745d2f79043d4921ef5de0 Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Mon, 7 Sep 2026 23:28:24 -0700 Subject: [PATCH 04/11] fix(fixtures): make mutation template byte-stable across time openpyxl stamps dcterms:modified with save time, so the committed fixture drifted on every test run that rebuilt it. The builder now rewrites the modified timestamp to the fixed epoch in its ZIP repack stage; the artifact and manifest are regenerated against the pinned bytes and the recorded template_sha256 matches the committed fixture again. The regenerable tier4_manifest_fragment.json merge byproduct is untracked. Verification: two builds 2s apart produce identical bytes; mutation suite rerun preserved scores (60/100/60/0) with matching artifact SHA; tests/test_mutation_suite.py 7 passed. --- fixtures/excel/tier4_manifest_fragment.json | 181 ------------------ fixtures/mutation/manifest.json | 2 +- .../mutation/template_corporate_model.xlsx | Bin 15043 -> 15030 bytes results-2026-09-08/mutation/README.md | 12 +- .../aspose-cells-foss/repeat-1-input.xlsx | Bin 15042 -> 15030 bytes .../aspose-cells-foss/repeat-1-output.xlsx | Bin 14832 -> 14820 bytes .../aspose-cells-foss/repeat-2-input.xlsx | Bin 15042 -> 15030 bytes .../aspose-cells-foss/repeat-2-output.xlsx | Bin 14832 -> 14820 bytes .../aspose-cells-foss/repeat-3-input.xlsx | Bin 15042 -> 15030 bytes .../aspose-cells-foss/repeat-3-output.xlsx | Bin 14832 -> 14820 bytes .../mutation/openpyxl/repeat-1-input.xlsx | Bin 15042 -> 15030 bytes .../mutation/openpyxl/repeat-1-output.xlsx | Bin 14099 -> 14100 bytes .../mutation/openpyxl/repeat-2-input.xlsx | Bin 15042 -> 15030 bytes .../mutation/openpyxl/repeat-2-output.xlsx | Bin 14100 -> 14100 bytes .../mutation/openpyxl/repeat-3-input.xlsx | Bin 15042 -> 15030 bytes .../mutation/openpyxl/repeat-3-output.xlsx | Bin 14100 -> 14100 bytes results-2026-09-08/mutation/results.json | 18 +- .../mutation/wolfxl/repeat-1-input.xlsx | Bin 15042 -> 15030 bytes .../mutation/wolfxl/repeat-1-output.xlsx | Bin 15726 -> 15714 bytes .../mutation/wolfxl/repeat-2-input.xlsx | Bin 15042 -> 15030 bytes .../mutation/wolfxl/repeat-2-output.xlsx | Bin 15726 -> 15714 bytes .../mutation/wolfxl/repeat-3-input.xlsx | Bin 15042 -> 15030 bytes .../mutation/wolfxl/repeat-3-output.xlsx | Bin 15726 -> 15714 bytes .../mutation/zavora-xlsx/repeat-1-input.xlsx | Bin 15042 -> 15030 bytes .../mutation/zavora-xlsx/repeat-2-input.xlsx | Bin 15042 -> 15030 bytes .../mutation/zavora-xlsx/repeat-3-input.xlsx | Bin 15042 -> 15030 bytes scripts/build_mutation_template.py | 9 + 27 files changed, 25 insertions(+), 197 deletions(-) delete mode 100644 fixtures/excel/tier4_manifest_fragment.json diff --git a/fixtures/excel/tier4_manifest_fragment.json b/fixtures/excel/tier4_manifest_fragment.json deleted file mode 100644 index c26f126..0000000 --- a/fixtures/excel/tier4_manifest_fragment.json +++ /dev/null @@ -1,181 +0,0 @@ -{ - "generated_at": "2026-09-08T05:26:38.636308+00:00", - "excel_version": "none", - "generator_version": "0.1.0", - "generator": "openpyxl-structural", - "file_format": "xlsx", - "files": [ - { - "path": "tier4/20_sheet_protection.xlsx", - "feature": "sheet_protection", - "tier": 4, - "file_format": "xlsx", - "test_cases": [ - { - "id": "prot_basic", - "label": "Protection: basic (OOXML defaults)", - "row": 2, - "sheet": "sheet_protection_basic", - "expected": { - "protection": { - "protected": true, - "password_hash_present": false, - "format_cells": true, - "insert_rows": true, - "select_locked_cells": false, - "select_unlocked_cells": false, - "sort": true, - "auto_filter": true - } - }, - "importance": "basic" - }, - { - "id": "prot_password", - "label": "Protection: with password hash", - "row": 2, - "sheet": "sheet_protection_password", - "expected": { - "protection": { - "protected": true, - "password_hash_present": true, - "format_cells": true, - "insert_rows": true, - "select_locked_cells": false, - "select_unlocked_cells": false, - "sort": true, - "auto_filter": true, - "password": "bench-secret" - } - }, - "importance": "basic" - }, - { - "id": "prot_granular", - "label": "Protection: granular attribute flags", - "row": 2, - "sheet": "sheet_protection_granular", - "expected": { - "protection": { - "protected": true, - "password_hash_present": false, - "format_cells": false, - "insert_rows": true, - "select_locked_cells": true, - "select_unlocked_cells": false, - "sort": false, - "auto_filter": true - } - }, - "importance": "edge" - } - ] - }, - { - "path": "tier4/21_page_setup.xlsx", - "feature": "page_setup", - "tier": 4, - "file_format": "xlsx", - "test_cases": [ - { - "id": "page_setup_landscape", - "label": "Page setup: landscape + fit-to-width", - "row": 2, - "sheet": "page_setup_landscape", - "expected": { - "page_setup": { - "orientation": "landscape", - "fit_to_width": 1, - "fit_to_height": null, - "scale": null, - "print_title_rows": null, - "header_center": null, - "footer_center": null - } - }, - "importance": "basic" - }, - { - "id": "page_setup_scale", - "label": "Page setup: portrait at 75% scale", - "row": 2, - "sheet": "page_setup_scale", - "expected": { - "page_setup": { - "orientation": "portrait", - "fit_to_width": null, - "fit_to_height": null, - "scale": 75, - "print_title_rows": null, - "header_center": null, - "footer_center": null - } - }, - "importance": "basic" - }, - { - "id": "page_setup_titles", - "label": "Page setup: print titles + header/footer", - "row": 2, - "sheet": "page_setup_titles", - "expected": { - "page_setup": { - "orientation": null, - "fit_to_width": null, - "fit_to_height": null, - "scale": null, - "print_title_rows": "$1:$2", - "header_center": "ExcelBench Report", - "footer_center": "Page &P" - } - }, - "importance": "edge" - } - ] - }, - { - "path": "tier4/22_chart_anchor.xlsx", - "feature": "chart_anchor", - "tier": 4, - "file_format": "xlsx", - "test_cases": [ - { - "id": "chart_bar", - "label": "Chart: bar with twoCell anchor", - "row": 2, - "expected": { - "charts": [ - { - "type": "bar", - "anchor_type": "twoCell", - "from": "B2", - "to": "H12", - "data_ref": "E2:E8", - "categories_ref": "F2:F8" - } - ] - }, - "importance": "basic" - }, - { - "id": "chart_line", - "label": "Chart: line with twoCell anchor", - "row": 2, - "expected": { - "charts": [ - { - "type": "line", - "anchor_type": "twoCell", - "from": "J2", - "to": "P12", - "data_ref": "E2:E8", - "categories_ref": "F2:F8" - } - ] - }, - "importance": "edge" - } - ] - } - ] -} diff --git a/fixtures/mutation/manifest.json b/fixtures/mutation/manifest.json index 45287af..45d5f46 100644 --- a/fixtures/mutation/manifest.json +++ b/fixtures/mutation/manifest.json @@ -6,7 +6,7 @@ "customXml/item1.xml": "e9add2e6b47913324315bf91125bcce244eee364ba11ec00803e226674fe35b1", "customXml/itemProps1.xml": "de62706849294a697ecf047953b54c0183a264d5226ef3f43cf3ce47d2ee3662", "docProps/app.xml": "209fca6b00afe72a5029754b94be5953d8f16d96f67130325566b9366ad4ccc5", - "docProps/core.xml": "e4fb90e29af41c5d404c9b110cd1be7184f46a2767a2aea64160b29771a25a21", + "docProps/core.xml": "1c9e31d7cf7baceb04f5faa336474660ba29c65b98bb2f432c095844125e5c59", "xl/_rels/workbook.xml.rels": "9f80b92319d8b9c20f25d718624b941fcbb42403a9f86fe137722889b35d4b87", "xl/charts/chart1.xml": "54c98567bbe1b8340e8e0cd4dac37b07ed37a4fedf59832db1ef04499daf0eaf", "xl/charts/chart2.xml": "2c793da99c3bcf4e2f96daad7ae96f14be96703e1c5cb243255767e844d29f59", diff --git a/fixtures/mutation/template_corporate_model.xlsx b/fixtures/mutation/template_corporate_model.xlsx index a5cbfa50fa973eac9ec2dd87bc2248ec9d888960..861425023f9d7984e3e35bc28a7cc8fffc902707 100644 GIT binary patch delta 458 zcmX?Hx~+7BCmZWYqtXelC;PF<)t}EgY`}9YKJ~}E6P^p%CqLV?DVV!i)U3>S+pSqg z>o=HA+V@vxy|3hLW}cFXUtTWvU*N~Ou;$3~7tC%(Gvw5)cc_Hi*kBwez~DLe;;E4I z*3)Mf_lE`fJ?3l*k^j_kp=cjlx5`!(PU8(++!Mdf4Rdmx^5n7T`m0U+^9wZ$)-tfy zZ+W5N7;JvvS7q`JA7}RR13bz-X0_r0`bUEP3P)QVSa(WurmJaRvhBJqz55pq+^+i` zbZ%{rx60f@HdA{Rcpu>1om&@co5%0JCckp`x{Aq<5A4+VXjlFB;rqNBRk?l7 znHG~f$K(PIvB@o_0+Ua132*~-ff|m+pN69QNFA&*UZU zr~cXYbgIVnruF+J<5^}))&1>$CLG|+%p$_Tz%bdxOl)&8`wTs3kO-KCFeR~1E@YRP zY-TDjIg~?y8>k8l8W=++uQhXI+%x$-kTjWWXzt1+#5Y-yPj&KKb1lZ_lTVoYGT91F z_7Rkte8fy(@@gSuy{jh2SXeRUO`dMy$hdOyO$!IcSCgeIZJ3VAO=eV(p8Q^pYjUln t7SktrAXjzrIUw_Z!ej?4(aHQ)`i$n2?X6syEDgW{v#mtgYE3{+0su24w;})l diff --git a/results-2026-09-08/mutation/README.md b/results-2026-09-08/mutation/README.md index 5a33b0a..e44a2e6 100644 --- a/results-2026-09-08/mutation/README.md +++ b/results-2026-09-08/mutation/README.md @@ -1,17 +1,17 @@ # ExcelBench Mutation Results -*Generated: 2026-09-08T05:42:21Z* -*Template SHA-256: 74de96e1ea2b6ee8d52e9ff13b51db36d9140b371194afa1b70bba7158feca5b* +*Generated: 2026-09-08T06:28:04Z* +*Template SHA-256: da08cc9e607f267b438ec7ce2480d6eb3650d1c19928f283a18296a2b79d808e* *Repeats: 3* ## Comparison | Engine | Wall ms | Peak RSS KB | Preservation score | Lost parts | Verdict | |--------|---------|-------------|--------------------|------------|---------| -| aspose-cells-foss | 770.000 | 170848.000 | 60.000 | 3 | Loss detected | -| openpyxl | 750.000 | 170336.000 | 60.000 | 3 | Loss detected | -| wolfxl | 780.000 | 175696.000 | 100.000 | 0 | Preserved | -| zavora-xlsx | 1320.000 | 169568.000 | 0.000 | 1 | Mutation integrity failed | +| aspose-cells-foss | 690.000 | 170752.000 | 60.000 | 3 | Loss detected | +| openpyxl | 710.000 | 170336.000 | 60.000 | 3 | Loss detected | +| wolfxl | 710.000 | 175488.000 | 100.000 | 0 | Preserved | +| zavora-xlsx | 1270.000 | 169520.000 | 0.000 | 1 | Mutation integrity failed | ## Notes diff --git a/results-2026-09-08/mutation/aspose-cells-foss/repeat-1-input.xlsx b/results-2026-09-08/mutation/aspose-cells-foss/repeat-1-input.xlsx index aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7..861425023f9d7984e3e35bc28a7cc8fffc902707 100644 GIT binary patch delta 408 zcmV;J0cZZgb+&b|Nd^VUGIfyalTHR6f6r>eFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;fHJx{osJtnhZNq*WEGVKPHA=!z}38on~c$T*x5JrnZc#a>N=vNs%) zc9~d&2=L$XdUd$|>b4sJ-~6HvSSm*A91QleJt}Nqs4ZBlY#BZA+2Jzd24fyskAQm* zb4 z2H)~0YZAm(T;DdYE#cTg?T?W~g=go^-E`pbhp@s|Ie~Fz+sn_&UA5FXxt;T*lSzw6 z@gCm;@n7p#7`^$V@UJnJA@Svpq}QciSdpW0bG6YKaOirP*n>i~%fuW+9X4?Thq0+O zi1ILX0a1OX{vhhUsRM{oGy@B!oB4ovTOqvP5X#XUta6e$SmhN6C1wHE5Mu$BTWetn k()YpwtVGMw9w`!wEX_c2t1M+0lP4dyRA$pR0j4|#0NSb-?*IS* delta 660 zcmaD-{Gpg9z?+#xgn@y9gTa04MxHB-OzvAZKVlRG(?6Mvz_c#QCorwZ7Q+RSuNQ~` z^Y02;g6PQ-!goNz--JV$K(vq8X%-MIDJ=}5C+o?71#wjs(!kQaN@ZZ0RW%!|yGZRa zNZMWf5J-43x7HO9_o0?O8>jnL_1FUk-xg_2)-;r<@15xDf7pPh?fq}j(093){CWhp z-eue(?BOBOSk^6+-<@GMg=N>@>Pvmo7_9|<3hiG%-=b`%)e5tp49}Nd6g_3!By`~p z$I5cis=RA2g;ebfbR)7&LSAslt$h`FQupbxgNu#DVkSJ8%yDU6QS`!Ej%i76e#(h_ zjx2ehk=GlnbEJOt?ZneRq;E6oaYQDtHgbwdylY%Jx8nu3=8u*w@7KvPG$m&^HuA|m zkL=sOmvPP~ac;J!XI7?IMD56sJ$kbCLy=Kg?DW#l2c>?W|M>dw-^(AahPaHsfA;gtJfz9Ud56Q zU;aOV|GQT`(%b$?{>JPnI?_e1-PyC|C%ZeuSpD1lwdxxuaeFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;fHJx{osJtnhZNq*WEGVKPHA=!z}38on~c$T*x5JrnZc#a>N=vNs%) zc9~d&2=L$XdUd$|>b4sJ-~6HvSSm*A91QleJt}Nqs4ZBlY#BZA+2Jzd24fyskAQm* zb4 z2H)~0YZAm(T;DdYE#cTg?T?W~g=go^-E`pbhp@s|Ie~Fz+sn_&UA5FXxt;T*lSzw6 z@gCm;@n7p#7`^$V@UJnJA@Svpq}QciSdpW0bG6YKaOirP*n>i~%fuW+9X4?Thq0+O zi1ILX0a1OX{vhhUsRM{oGy@B!oB4ovTOqvP5X#XUta6e$SmhN6C1wHE5Mu$BTWetn k()YpwtVGMw9w`!wEX_c2t1M+0lP4dyRA$pR0j4|#0NSb-?*IS* delta 660 zcmaD-{Gpg9z?+#xgn@y9gTZ6#MxHB-OdeY|KVlRG(?6Mvz_c#QCorwZ7Q+RSuNQ~` z^Y02;g6PQ-!goNz--JV$K(vq8X%-MIDJ=}5C+o?71#wjs(!kQaN@ZZ0RW%!|yGZRa zNZMWf5J-43x7HO9_o0?O8>h!s_1FUk-xg_2)-;r<@15xDf7pPh?fq}j(093){CWhp z-eue(?BOBOSk^6+-<@GMg=N>@>Pvmo7_9|<3hiG%-=b`%)e5tp49}Nd6g_3!By`~p z$I5cis=RA2g;ebfbR)7&LSAslt$h`FQupbxgNu#DVkSJ8%yDU6QS`!Ej%i76e#(h_ zjx2ehk=GlnbEJOt?ZneRq;E6oaYQDtHgbwdylY%Jx8nu3=8u*w@7KvPG$m&^HuA|m zkL=sOmvPP~ac;J!XI7?IMD56sJ$kbCLy=Kg?DW#l2c>?W|M>dw-^(AahPaHsfA;gtJfz9Ud56Q zU;aOV|GQT`(%b$?{>JPnI?_e1-PyC|C%ZeuSpD1lwdxxuaeFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;fHJx{osJtnhZNq*WEGVKPHA=!z}38on~c$T*x5JrnZc#a>N=vNs%) zc9~d&2=L$XdUd$|>b4sJ-~6HvSSm*A91QleJt}Nqs4ZBlY#BZA+2Jzd24fyskAQm* zb4 z2H)~0YZAm(T;DdYE#cTg?T?W~g=go^-E`pbhp@s|Ie~Fz+sn_&UA5FXxt;T*lSzw6 z@gCm;@n7p#7`^$V@UJnJA@Svpq}QciSdpW0bG6YKaOirP*n>i~%fuW+9X4?Thq0+O zi1ILX0a1OX{vhhUsRM{oGy@B!oB4ovTOqvP5X#XUta6e$SmhN6C1wHE5Mu$BTWetn k()YpwtVGMw9w`!wEX_c2t1M+0lP4dyRA$pR0j4|#0C!;+Z2$lO delta 660 zcmaD-{Gpg9z?+#xgn@y9gTZ6#MxHB-OdeY|KVlRG(?6Mvz_c#QCorwZ7Q+RSuNQ~` z^Y02;g6PQ-!goNz--JV$K(vq8X%-MIDJ=}5C+o?71#wjs(!kQaN@ZZ0RW%!|yGZRa zNZMWf5J-43x7HO9_o0?O8>h!s_1FUk-xg_2)-;r<@15xDf7pPh?fq}j(093){CWhp z-eue(?BOBOSk^6+-<@GMg=N>@>Pvmo7_9|<3hiG%-=b`%)e5tp49}Nd6g_3!By`~p z$I5cis=RA2g;ebfbR)7&LSAslt$h`FQupbxgNu#DVkSJ8%yDU6QS`!Ej%i76e#(h_ zjx2ehk=GlnbEJOt?ZneRq;E6oaYQDtHgbwdylY%Jx8nu3=8u*w@7KvPG$m&^HuA|m zkL=sOmvPP~ac;J!XI7?IMD56sJ$kbCLy=Kg?DW#l2c>?W|M>dw-^(AahPaHsfA;gtJfz9Ud56Q zU;aOV|GQT`(%b$?{>JPnI?_e1-PyC|C%ZeuSpD1lwdxxuaeFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;fVaG*wdO) zW`1LfqGaaxx4w__!VBdcPN*8!@B7IXq^*AC!N;5Ye72H2;*;P0QkW9GS$3i@gX7x^ zrzRYCk)J*LV6^AQSKA*f`86TBWzuIZok>?Fshl}*M%U%ql_<`qftMceSF9D=^ZQF| zQzq+;g-7QxiBvMKnW?_(Z~c|41x#lQobnHsGk$gQxw`qr6~;0Tzk@m}3uQhRPAw{I zXSz2}F8_AJfM{oING^@ z^yK|QcR<{^!XZo``m?AdBZ$@$*9Ozk5=^Whe!Q$R3y5B#m<@Ioarq49fw}7pZ4hxY`Lm%JNQ<_S4CAZG z9!5$aPL7cblQzfXd|A=S^Nj@MK@oZ7>4A_HpvYxpV2}XPFwnrbW%79=b&#$fKwXoB zC$AM&nrvar1J=cNwO@l1s3V1mfdP~>V4#8V#pGmTWst58V;Lr8@yT}Ls*_I}^MFKd z0!0EOz_vF?u<`|XGct)V!xGkHc@r6?5LuwCls2l2daR?^tDojT+satc-8ge{lL^?3 ztAV=NlqV}Ht4@Ar0=DfBP~^5U(0=L3rlw*b`+ZGi7*|ftG6g%YAIK4$yavL#2;_85 zerGBJQpRH@Q}3(8zz|=Qnp3Q=2O`lOw0YLrqw9bUGGk$2;D`AgNH;K==`t`>(JZJB)*N3ndAXS)$SJ4HWEhzzKQ~ijTWAPU F2>=%&K9c|d delta 885 zcmbP|H#v_dz?+#xgn@y9gTZy{M4p43u3Ob(uQD{R|32}WR{g6*3vYKn@^sv=po074 zo4gI4&PJEs-JX5y?z%<%3Qs1@w7*}&oH<22i{pm~TYn?ZvF?-K^thgy=lDNibqJ~6 zVl++jVNkI(i?(L$VZJ>f?~B?4iubW~t87)_G~V!md*asKFelb2CN0Wwt6AUMJIzmw zV*HkIF|cLTnue{PUFv7l|6)7WAn7KN^G9nzT*uB|>SpB)vXg^Nyt8DE7sWh{xwWwA z`tkPXd-4)vR9=cK3%|%=RdHv-U z|A8ON9$c5*FEoAYiha`aS#Gn{{q6oHj2sN=u`^@lC=0MLZ2r$^#>V8jb+b7~I~S0i zd_d?9h&xX>gb74{5w&Cl(fZ=rU^+&Ei50|8kacDO(MuJxLE@8zlrMv*=gMb5qFYtc zz`AAC%fR$h%|jr1a-`04khGKTO|T|e{SP26zrj2(cfFwvB5o#sF*E~d(J_)?d^y?E zND0KrHIiY{;+R|@D>`|Bk)S*%BCk9>5V8Ukxr_`95F#|D*W`W5I%rrr^oi>wUVltR4Zy-APpP2yL I0z;580LfD<9{>OV diff --git a/results-2026-09-08/mutation/openpyxl/repeat-2-input.xlsx b/results-2026-09-08/mutation/openpyxl/repeat-2-input.xlsx index aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7..861425023f9d7984e3e35bc28a7cc8fffc902707 100644 GIT binary patch delta 408 zcmV;J0cZZgb+&b|Nd^VUGIfyalTHR6f6r>eFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;f*j#G!{1!|7+AKt zYdgyc*XHE0=c^uFeZO(?E9Z9tUgxwocm#P*GGI2|E)W@}pxi>yrEjm%H4U%lH`o8Wu$wAN!+8{OwhbHCsGI{kj+4Zd4B zXIUlgr~O&>bgIVsqg8(o|4_Mc<-_xMlX&ECP>-D%Ge=oq^It{_Hm2&`o6R}exq$TK z144H|+KSNS3Uz0-KvrX z)-9`E2BxQK9s<#mBXypGq@8qcf;GwNe*kg$4d#Kl>kVz-Q8W3op*cv0j*&fx$~AHU zQJW#uPa_`?&)wJoM0FbbgQ#1^U?mDBU@8qltuX=1{e@6|reF;dAk-yOOOQTZGq6Q& QX4W8HvzZ%+I&J0&0E$%j4*&oF delta 570 zcmbP|HzkiJz?+#xgn@y9gTZy{M4p2ju3Ob(OD0TlpLkWP{^hGh3vYKn@^sv=po074 zo4gH~&PJEs-JX5y?z%<%3Qs1@w7*}&ymIUGDvlo_Z2gTo$GT6J)=s&Ve`DSW?}ioM zUxercFY-V8R$$Je5?<>MUi(+eIvxEfB{RvWOXSRfL;5b)uDE&223!>At5__)=RZem znt*Js4JYQKC?c-U`peAxE#x3<|@acjBtE@fIy|GDSvI{QE84&@n? zW&dyd=zDN|be*ccw&oG@$CDF+53jGkSi^)I4(hQpW9BFeZ2rq=!N%meb+b7~I~S0i zd_d?9h&xX>gb74{5w&Cl(fZ=rU^+&Ei50|8kacDO(MuJxLE@8zlrMv*=gMb5qFYtc zz`AAC%fR$h%|jr1a-`04khGKTO|T|e{SP26zrj2(cfFwvJZdI?HZ%w6&@r+HQMpDg zAZjy&`f20?;<+0;fT&Jme-L%c7_3CW1Wctts5K^FxxWy~&lId-0))C`Y6;TEYX-K+ Q&CD9aYc_KOQK!v30b@Mx?*IS* diff --git a/results-2026-09-08/mutation/openpyxl/repeat-3-input.xlsx b/results-2026-09-08/mutation/openpyxl/repeat-3-input.xlsx index aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7..861425023f9d7984e3e35bc28a7cc8fffc902707 100644 GIT binary patch delta 408 zcmV;J0cZZgb+&b|Nd^VUGIfyalTHR6f6r>eFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;f*j#G!{1!|7+AKt zYdgyc*XHE0=c^uFeZO(?E9Z9tUgxwocm#P*GGI2|E)W@}pxi>yrEjm%H4U%lH`o8Wu$wAN!+8{OwhbHCsGI{kj+4Zd4B zXIUlgr~O&>bgIVsqg8(o|4_Mc<-_xMlX&ECP>-D%Ge=oq^It{_Hm2&`o6R}exq$TK z144H|+KSNS3Uz0-KvrX z)-9`E2BxQK9s<#mBXypGq@8qcf;GwNe*kg$4d#Kl>kVz-Q8W3op*cv0j*&fx$~AHU zQJW#uPa_`?&)wJoM0FbbgQ#1^U?mDBU@8qltuX=1{e@6|reF;dAk-yOOOQTZGq6Q& QX4W8HvzZ%+I&J0&0E$%j4*&oF delta 570 zcmbP|HzkiJz?+#xgn@y9gTZau)Z)x` zt~h!5d7pQ+zExfsms};fc1iPbUTfdF$h-HpeqSRPvxYlv>E$B5&y}-d>wnB`y_@jn z+CS#Uvzy|#|M80BitNlkrhaf)Tm1h;KUt8&K|OY6%p7Hb&3_p!*qGe5ZZ_v==K|7` z4+z}>apwt#FoEbVqLz#xT3=inOvgwtv4Z#svd%0ZdZ}VINPM!8@?{Y9T=@)0bgN1l zShuWt8JM1`c?d*Lj?{S$l6KO)3DzX5{{h71H<$nSwP;fKZoAEkXKt&A=A9 QnOTE)&1P;O>a>|B077!_K>z>% diff --git a/results-2026-09-08/mutation/results.json b/results-2026-09-08/mutation/results.json index 7e825a9..4ab0745 100644 --- a/results-2026-09-08/mutation/results.json +++ b/results-2026-09-08/mutation/results.json @@ -180,10 +180,10 @@ "missing_content_types": [], "mutations_landed": true }, - "peak_rss_kb_median": 170848.0, + "peak_rss_kb_median": 170752.0, "preservation_score": 60.0, "status": "passed", - "wall_ms_median": 770.0 + "wall_ms_median": 690.0 }, "openpyxl": { "available": true, @@ -366,7 +366,7 @@ "peak_rss_kb_median": 170336.0, "preservation_score": 60.0, "status": "passed", - "wall_ms_median": 750.0 + "wall_ms_median": 710.0 }, "wolfxl": { "available": true, @@ -544,10 +544,10 @@ "missing_content_types": [], "mutations_landed": true }, - "peak_rss_kb_median": 175696.0, + "peak_rss_kb_median": 175488.0, "preservation_score": 100.0, "status": "passed", - "wall_ms_median": 780.0 + "wall_ms_median": 710.0 }, "zavora-xlsx": { "available": true, @@ -728,16 +728,16 @@ "missing_content_types": [], "mutations_landed": false }, - "peak_rss_kb_median": 169568.0, + "peak_rss_kb_median": 169520.0, "preservation_score": 0.0, "status": "integrity-failed", - "wall_ms_median": 1320.0 + "wall_ms_median": 1270.0 } }, "metadata": { "platform": "Darwin", "repeats": 3, - "template_sha256": "74de96e1ea2b6ee8d52e9ff13b51db36d9140b371194afa1b70bba7158feca5b", - "timestamp": "2026-09-08T05:42:21Z" + "template_sha256": "da08cc9e607f267b438ec7ce2480d6eb3650d1c19928f283a18296a2b79d808e", + "timestamp": "2026-09-08T06:28:04Z" } } diff --git a/results-2026-09-08/mutation/wolfxl/repeat-1-input.xlsx b/results-2026-09-08/mutation/wolfxl/repeat-1-input.xlsx index aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7..861425023f9d7984e3e35bc28a7cc8fffc902707 100644 GIT binary patch delta 408 zcmV;J0cZZgb+&b|Nd^VUGIfyalTHR6f6r>eFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;feFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%Rwf3)Z* zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTDd zO9KQH000080000XT&3-r0r~&{vycaKEdqQqvjsJP0|m)4b&%_mia1mOZX0`?Y@R69QbH)*C_Nkj?UO}4BL?0!00000cpA46 delta 463 zcmV;=0WkjJdhU9#V+I8kB%M4fT;KAR4h}X zPtENRoT79MJMc=ss~tkk`5GLOGKv(;z``#?CL5!L4yb4dN4(Js-hYHH!;A*(f6!r1 z5vsBRCg+L%Fm(-_0W*v+xcF5-vk-IjPi*c0J0_=Sm()0p<+#eZv_l22j}Omz-NN>f zRIf3;idN9U!8EdoX@v-vcD0|gZ%ol^IcemGPDdk2$?2ON{| zI4S|HlN&if0Tq*7IY9x9lb<<70&5PFdk!U&3py$SKo65p4`97lSn&10Yj6BJ3InUACq4nC6ntrDgt~UlV2YjlQKLs0!ks1S|J*f z0IXxo=>NWrX F002~%zE%JL diff --git a/results-2026-09-08/mutation/wolfxl/repeat-2-input.xlsx b/results-2026-09-08/mutation/wolfxl/repeat-2-input.xlsx index aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7..861425023f9d7984e3e35bc28a7cc8fffc902707 100644 GIT binary patch delta 408 zcmV;J0cZZgb+&b|Nd^VUGIfyalTHR6f6r>eFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;feFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%Rwf3)Z* zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTDd zO9KQH000080000XT&3-r0r~&{vycaKEdqQqvjsJP0|m)4b&%_mia1mOZX0`?Y@R69QbH)*C_Nkj?UO}4BL?0!00000cpA46 delta 463 zcmV;=0WkjJdhU9#V+I8kB%M4fT;KAR4h}X zPtENRoT79MJMc=ss~tkk`5GLOGKv(;z``#?CL5!L4yb4dN4(Js-hYHH!;A*(f6!r1 z5vsBRCg+L%Fm(-_0W*v+xcF5-vk-IjPi*c0J0_=Sm()0p<+#eZv_l22j}Omz-NN>f zRIf3;idN9U!8EdoX@v-vcD0|gZ%ol^IcemGPDdk2$?2ON{| zI4S|HlN&if0Tq*7IY9x9lb<<70&5PFdk!U&3py$SKo65p4`97lSn&10Yj6BJ3InUACq4nC6ntrDgt~UlV2YjlQKLs0!ks1S|J*f z0IXxo=>NWrX F002~%zE%JL diff --git a/results-2026-09-08/mutation/wolfxl/repeat-3-input.xlsx b/results-2026-09-08/mutation/wolfxl/repeat-3-input.xlsx index aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7..861425023f9d7984e3e35bc28a7cc8fffc902707 100644 GIT binary patch delta 408 zcmV;J0cZZgb+&b|Nd^VUGIfyalTHR6f6r>eFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;feFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%Rwf3)Z* zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTDd zO9KQH000080000XT&3-r0r~&{vycaKEdqTrvjsJP0|m)4b&%_mia1mOZX0`?Y@R69QbH4fT;KAR4h}X zPtENRoT79MJMc=ss~tkk`5GLOGKv(;z``#?CL5!L4yb4dN4(Js-hYHH!;A*(f6!r1 z5vsBRCg+L%Fm(-_0W*v+xcF5-vk-IjPi*c0J0_=Sm()0p<+#eZv_l22j}Omz-NN>f zRIf3;idN9U!8Edoa^v-vcD0|gZ%ol^IcemGPDdk2$?2ON{| zI4S|HlN&if0Tq*7IY9x9lb<<70&5PFdk!U&3py$SKo65p4`97lSn&10Yj6BJ3InUACq4nC6ntrDgt~UlV2YjlQKLs0!ks1S|J*f z0IXxo=>NWrX F0032DzE}VN diff --git a/results-2026-09-08/mutation/zavora-xlsx/repeat-1-input.xlsx b/results-2026-09-08/mutation/zavora-xlsx/repeat-1-input.xlsx index aeea7dc1152a27ee11cb26c2ee65a3b27474d7a7..861425023f9d7984e3e35bc28a7cc8fffc902707 100644 GIT binary patch delta 408 zcmV;J0cZZgb+&b|Nd^VUGIfyalTHR6f6r>eFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;feFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;feFbu|DW%!=RNudXm=CZO=3xgFlb~Cox zn#F&xHIlyl9Is6o+XD=Ak@V@OPoPc(p?t*W=mSPFm>woOxFl5AurpB*07;$E%2a2C z%gv*YR#Hym34&A~@`TWGz6OgVwIm5MunG&2^_^BiMU>>@6|dET51(-;Fs%RwYP9Gm zK~p!t`gvoxOhX5EzziddHhmXRFT_&)6I(jKuF5HyMKz9NJ+6u_-_XF@e)m$&t&B?~ zox(hojG#-v4ZCfAT|I6OPpofwyRLYX^u1N7yTEr zVF$J@1<5jXkn58iHdFyslW{gj0!IjwZwMBX&^9Uouao;WK>{ZYlTQsAlUO$@0tF6} zEe<7<+Bp!Dxi=aC+LP2bO#v{IA~;0>os(!dIssvmqc}kUoRj4^Kmpy8COJF;xE_<> z9wn37IS`YXIT`}xACur78Y00000B CGOQQ? delta 462 zcmdm1dZ=`RCmXA%%G{vull|D_>JNGyF%W2rcP+|SfBR_F!r9%AJRLVIsNg>NCT~Ng zv(cq@w`U)_yKWJ`!jnle?eEtxXKoR%;`kxL*59aetovkXt;ntX8}m+ZH>~*nB19*6 zk^kAZ0&^CX@LGTH+P_-X>FiG_nMp=nB4-X9(sxmlUfjyJB7?(y&qeNg^(}gbd)VI8 zUr6*9T(yZw?Rn=vgHql(jK)0%JAQ;ZY!)c~>YwwD!CGy3#`G%|eNT6s+PTGdN<+CwSUZy zXE()f{}Xg2e9^DG8lfq?e}0L75)SZYW)WdvVBnbSY9_k5n0kL>zztLe1`UkClh>L#GVY%I9!MHbHZ*r-66Bk#$fr7auDKTDv&kpSeVJ?o zC;JFWO+I2KFnP5Qvfh=GV=Sx~b0<%?aAaID`KE;f None: Target=\"itemProps1.xml\"/> """ + core = parts["docProps/core.xml"].decode("utf-8") + core = re.sub( + r"(]*>)[^<]*()", + r"\g<1>2026-01-01T00:00:00Z\g<2>", + core, + ) + parts["docProps/core.xml"] = core.encode("utf-8") + with ZipFile(path, "w", compression=ZIP_DEFLATED, compresslevel=9) as archive: for name in sorted(parts): info = ZipInfo(filename=name, date_time=FIXED_TIMESTAMP) From 38648dd478a8f371ca1d6c88ad4dc1abd4bf1e05 Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Mon, 7 Sep 2026 23:30:16 -0700 Subject: [PATCH 05/11] fix(tests): guard aspose module import before adapter import importorskip ran after the module-level adapter import, which raises ImportError when the extra is missing; the guard now precedes it so CI environments without the 'aspose' extra collect-skip the module. --- tests/test_aspose_cells_foss_adapter.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/test_aspose_cells_foss_adapter.py b/tests/test_aspose_cells_foss_adapter.py index 8b5e7bb..c2a1935 100644 --- a/tests/test_aspose_cells_foss_adapter.py +++ b/tests/test_aspose_cells_foss_adapter.py @@ -6,9 +6,13 @@ import pytest -from excelbench.harness.adapters.aspose_cells_foss_adapter import AsposeCellsFossAdapter -from excelbench.harness.adapters.base import UnsupportedAdapterOperationError -from excelbench.models import ( +pytest.importorskip("aspose.cells_foss", reason="optional 'aspose' extra not installed") + +from excelbench.harness.adapters.aspose_cells_foss_adapter import ( + AsposeCellsFossAdapter, # noqa: E402 +) +from excelbench.harness.adapters.base import UnsupportedAdapterOperationError # noqa: E402 +from excelbench.models import ( # noqa: E402 BorderEdge, BorderInfo, BorderStyle, @@ -17,8 +21,6 @@ CellValue, ) -pytest.importorskip("aspose.cells_foss", reason="optional 'aspose' extra not installed") - @pytest.fixture def adapter() -> AsposeCellsFossAdapter: From 9f62b7ad5246c8d2340b01048a431e9f1811cd07 Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Mon, 7 Sep 2026 23:36:20 -0700 Subject: [PATCH 06/11] fix(ci): make LibreOffice-dependent tests environment-gated CI runners have no soffice binary at the hardcoded homebrew path. Resolve the binary via PATH first (homebrew fallback kept), and skip the three LibreOffice-dependent tests (calc builder regeneration, engine smoke, mutation template PDF render) when it is absent. The wolfxl calc-engine assertion engages only on wolfxl >= 2.1, matching the calculate() API the engine requires. Verification: ruff clean; mypy 0 issues; pytest 1235 passed locally; with soffice hidden the two calc tests skip with reason and the mutation LO test carries the same guard. --- fixtures/excel/tier4_manifest_fragment.json | 181 ++++++++++++++++++++ src/excelbench/harness/calc.py | 4 +- tests/test_calc_suite.py | 26 ++- tests/test_mutation_suite.py | 8 +- 4 files changed, 214 insertions(+), 5 deletions(-) create mode 100644 fixtures/excel/tier4_manifest_fragment.json diff --git a/fixtures/excel/tier4_manifest_fragment.json b/fixtures/excel/tier4_manifest_fragment.json new file mode 100644 index 0000000..c26f126 --- /dev/null +++ b/fixtures/excel/tier4_manifest_fragment.json @@ -0,0 +1,181 @@ +{ + "generated_at": "2026-09-08T05:26:38.636308+00:00", + "excel_version": "none", + "generator_version": "0.1.0", + "generator": "openpyxl-structural", + "file_format": "xlsx", + "files": [ + { + "path": "tier4/20_sheet_protection.xlsx", + "feature": "sheet_protection", + "tier": 4, + "file_format": "xlsx", + "test_cases": [ + { + "id": "prot_basic", + "label": "Protection: basic (OOXML defaults)", + "row": 2, + "sheet": "sheet_protection_basic", + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true + } + }, + "importance": "basic" + }, + { + "id": "prot_password", + "label": "Protection: with password hash", + "row": 2, + "sheet": "sheet_protection_password", + "expected": { + "protection": { + "protected": true, + "password_hash_present": true, + "format_cells": true, + "insert_rows": true, + "select_locked_cells": false, + "select_unlocked_cells": false, + "sort": true, + "auto_filter": true, + "password": "bench-secret" + } + }, + "importance": "basic" + }, + { + "id": "prot_granular", + "label": "Protection: granular attribute flags", + "row": 2, + "sheet": "sheet_protection_granular", + "expected": { + "protection": { + "protected": true, + "password_hash_present": false, + "format_cells": false, + "insert_rows": true, + "select_locked_cells": true, + "select_unlocked_cells": false, + "sort": false, + "auto_filter": true + } + }, + "importance": "edge" + } + ] + }, + { + "path": "tier4/21_page_setup.xlsx", + "feature": "page_setup", + "tier": 4, + "file_format": "xlsx", + "test_cases": [ + { + "id": "page_setup_landscape", + "label": "Page setup: landscape + fit-to-width", + "row": 2, + "sheet": "page_setup_landscape", + "expected": { + "page_setup": { + "orientation": "landscape", + "fit_to_width": 1, + "fit_to_height": null, + "scale": null, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "importance": "basic" + }, + { + "id": "page_setup_scale", + "label": "Page setup: portrait at 75% scale", + "row": 2, + "sheet": "page_setup_scale", + "expected": { + "page_setup": { + "orientation": "portrait", + "fit_to_width": null, + "fit_to_height": null, + "scale": 75, + "print_title_rows": null, + "header_center": null, + "footer_center": null + } + }, + "importance": "basic" + }, + { + "id": "page_setup_titles", + "label": "Page setup: print titles + header/footer", + "row": 2, + "sheet": "page_setup_titles", + "expected": { + "page_setup": { + "orientation": null, + "fit_to_width": null, + "fit_to_height": null, + "scale": null, + "print_title_rows": "$1:$2", + "header_center": "ExcelBench Report", + "footer_center": "Page &P" + } + }, + "importance": "edge" + } + ] + }, + { + "path": "tier4/22_chart_anchor.xlsx", + "feature": "chart_anchor", + "tier": 4, + "file_format": "xlsx", + "test_cases": [ + { + "id": "chart_bar", + "label": "Chart: bar with twoCell anchor", + "row": 2, + "expected": { + "charts": [ + { + "type": "bar", + "anchor_type": "twoCell", + "from": "B2", + "to": "H12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "importance": "basic" + }, + { + "id": "chart_line", + "label": "Chart: line with twoCell anchor", + "row": 2, + "expected": { + "charts": [ + { + "type": "line", + "anchor_type": "twoCell", + "from": "J2", + "to": "P12", + "data_ref": "E2:E8", + "categories_ref": "F2:F8" + } + ] + }, + "importance": "edge" + } + ] + } + ] +} diff --git a/src/excelbench/harness/calc.py b/src/excelbench/harness/calc.py index 290a810..65d0d86 100644 --- a/src/excelbench/harness/calc.py +++ b/src/excelbench/harness/calc.py @@ -20,7 +20,9 @@ ) from excelbench.results.calc_renderer import render_calc_results -SOFFICE_PATH = Path("/opt/homebrew/bin/soffice") +SOFFICE_PATH = Path( + shutil.which("soffice") or "/opt/homebrew/bin/soffice" +) class CalcEngine(Protocol): diff --git a/tests/test_calc_suite.py b/tests/test_calc_suite.py index 5ac730f..163d1b6 100644 --- a/tests/test_calc_suite.py +++ b/tests/test_calc_suite.py @@ -9,7 +9,10 @@ from types import ModuleType from typing import Any, cast +import pytest + from excelbench.harness.calc import ( + SOFFICE_PATH, AsposeCellsFossCalcEngine, LibreOfficeCalcEngine, WolfXLCalcEngine, @@ -17,6 +20,10 @@ values_match, ) +requires_libreoffice = pytest.mark.skipif( + not SOFFICE_PATH.is_file(), reason="LibreOffice binary not available" +) + FIXTURE = Path("fixtures/calc/financial_model.xlsx") EXPECTED = Path("fixtures/calc/expected_values.json") @@ -34,6 +41,7 @@ def _load_fixture_builder() -> Callable[[Path, Path], dict[str, Any]]: build_fixture = _load_fixture_builder() +@requires_libreoffice def test_builder_regenerates_identical_expected_json(tmp_path: Path) -> None: fixture = tmp_path / "financial_model.xlsx" expected = tmp_path / "expected_values.json" @@ -67,13 +75,25 @@ def test_value_comparison_respects_tolerance_and_scalar_types() -> None: assert not values_match(True, 1) +@requires_libreoffice def test_local_wolfxl_and_libreoffice_engines_calculate(tmp_path: Path) -> None: - wolfxl_result = WolfXLCalcEngine().calculate(FIXTURE, tmp_path / "wolfxl.xlsx") + wolfxl_engine = WolfXLCalcEngine() + if wolfxl_engine.available(): + import wolfxl + + try: + major, minor = (int(part) for part in wolfxl.__version__.split(".")[:2]) + except (AttributeError, ValueError): + major, minor = 0, 0 + if (major, minor) >= (2, 1): + wolfxl_result = wolfxl_engine.calculate( + FIXTURE, tmp_path / "wolfxl.xlsx" + ) + assert wolfxl_result["status"] == "passed", wolfxl_result["reason"] + libreoffice_result = LibreOfficeCalcEngine().calculate( FIXTURE, tmp_path / "libreoffice.xlsx" ) - - assert wolfxl_result["status"] == "passed", wolfxl_result["reason"] assert libreoffice_result["status"] == "passed", libreoffice_result["reason"] diff --git a/tests/test_mutation_suite.py b/tests/test_mutation_suite.py index 9f79a31..5657b48 100644 --- a/tests/test_mutation_suite.py +++ b/tests/test_mutation_suite.py @@ -3,12 +3,14 @@ from __future__ import annotations import hashlib +import shutil import subprocess import sys from pathlib import Path from zipfile import ZIP_DEFLATED, ZipFile import openpyxl +import pytest from excelbench.harness.mutation import score_preservation from excelbench.modifiable import modifiable_engines @@ -17,7 +19,10 @@ REPO_ROOT = Path(__file__).resolve().parents[1] BUILDER = REPO_ROOT / "scripts" / "build_mutation_template.py" TEMPLATE = REPO_ROOT / "fixtures" / "mutation" / "template_corporate_model.xlsx" -SOFFICE = Path("/opt/homebrew/bin/soffice") +SOFFICE = Path(shutil.which("soffice") or "/opt/homebrew/bin/soffice") +requires_libreoffice = pytest.mark.skipif( + not SOFFICE.is_file(), reason="LibreOffice binary not available" +) def _sha256(path: Path) -> str: @@ -86,6 +91,7 @@ def test_builder_is_byte_stable() -> None: assert _sha256(TEMPLATE) == first_digest +@requires_libreoffice def test_template_opens_in_openpyxl_and_libreoffice(tmp_path: Path) -> None: """The committed fixture parses and LibreOffice renders it to PDF.""" workbook = openpyxl.load_workbook(TEMPLATE) From 54f575a81fb2bd6e7944e24724c3634bda382d87 Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Mon, 7 Sep 2026 23:36:42 -0700 Subject: [PATCH 07/11] chore(fixtures): gitignore the regenerable tier4 manifest fragment The tier4 builder test regenerates the merge byproduct with a fresh timestamp on every suite run, dirtying the tree; manifest.json is the merged source of truth. --- .gitignore | 3 + fixtures/excel/tier4_manifest_fragment.json | 181 -------------------- 2 files changed, 3 insertions(+), 181 deletions(-) delete mode 100644 fixtures/excel/tier4_manifest_fragment.json diff --git a/.gitignore b/.gitignore index 1ca3a1b..9baa337 100644 --- a/.gitignore +++ b/.gitignore @@ -103,3 +103,6 @@ output/ logs/ *.log .vercel + +# regenerable fixture-merge byproduct (scripts/build_tier4_fixtures.py) +fixtures/excel/tier4_manifest_fragment.json diff --git a/fixtures/excel/tier4_manifest_fragment.json b/fixtures/excel/tier4_manifest_fragment.json deleted file mode 100644 index c26f126..0000000 --- a/fixtures/excel/tier4_manifest_fragment.json +++ /dev/null @@ -1,181 +0,0 @@ -{ - "generated_at": "2026-09-08T05:26:38.636308+00:00", - "excel_version": "none", - "generator_version": "0.1.0", - "generator": "openpyxl-structural", - "file_format": "xlsx", - "files": [ - { - "path": "tier4/20_sheet_protection.xlsx", - "feature": "sheet_protection", - "tier": 4, - "file_format": "xlsx", - "test_cases": [ - { - "id": "prot_basic", - "label": "Protection: basic (OOXML defaults)", - "row": 2, - "sheet": "sheet_protection_basic", - "expected": { - "protection": { - "protected": true, - "password_hash_present": false, - "format_cells": true, - "insert_rows": true, - "select_locked_cells": false, - "select_unlocked_cells": false, - "sort": true, - "auto_filter": true - } - }, - "importance": "basic" - }, - { - "id": "prot_password", - "label": "Protection: with password hash", - "row": 2, - "sheet": "sheet_protection_password", - "expected": { - "protection": { - "protected": true, - "password_hash_present": true, - "format_cells": true, - "insert_rows": true, - "select_locked_cells": false, - "select_unlocked_cells": false, - "sort": true, - "auto_filter": true, - "password": "bench-secret" - } - }, - "importance": "basic" - }, - { - "id": "prot_granular", - "label": "Protection: granular attribute flags", - "row": 2, - "sheet": "sheet_protection_granular", - "expected": { - "protection": { - "protected": true, - "password_hash_present": false, - "format_cells": false, - "insert_rows": true, - "select_locked_cells": true, - "select_unlocked_cells": false, - "sort": false, - "auto_filter": true - } - }, - "importance": "edge" - } - ] - }, - { - "path": "tier4/21_page_setup.xlsx", - "feature": "page_setup", - "tier": 4, - "file_format": "xlsx", - "test_cases": [ - { - "id": "page_setup_landscape", - "label": "Page setup: landscape + fit-to-width", - "row": 2, - "sheet": "page_setup_landscape", - "expected": { - "page_setup": { - "orientation": "landscape", - "fit_to_width": 1, - "fit_to_height": null, - "scale": null, - "print_title_rows": null, - "header_center": null, - "footer_center": null - } - }, - "importance": "basic" - }, - { - "id": "page_setup_scale", - "label": "Page setup: portrait at 75% scale", - "row": 2, - "sheet": "page_setup_scale", - "expected": { - "page_setup": { - "orientation": "portrait", - "fit_to_width": null, - "fit_to_height": null, - "scale": 75, - "print_title_rows": null, - "header_center": null, - "footer_center": null - } - }, - "importance": "basic" - }, - { - "id": "page_setup_titles", - "label": "Page setup: print titles + header/footer", - "row": 2, - "sheet": "page_setup_titles", - "expected": { - "page_setup": { - "orientation": null, - "fit_to_width": null, - "fit_to_height": null, - "scale": null, - "print_title_rows": "$1:$2", - "header_center": "ExcelBench Report", - "footer_center": "Page &P" - } - }, - "importance": "edge" - } - ] - }, - { - "path": "tier4/22_chart_anchor.xlsx", - "feature": "chart_anchor", - "tier": 4, - "file_format": "xlsx", - "test_cases": [ - { - "id": "chart_bar", - "label": "Chart: bar with twoCell anchor", - "row": 2, - "expected": { - "charts": [ - { - "type": "bar", - "anchor_type": "twoCell", - "from": "B2", - "to": "H12", - "data_ref": "E2:E8", - "categories_ref": "F2:F8" - } - ] - }, - "importance": "basic" - }, - { - "id": "chart_line", - "label": "Chart: line with twoCell anchor", - "row": 2, - "expected": { - "charts": [ - { - "type": "line", - "anchor_type": "twoCell", - "from": "J2", - "to": "P12", - "data_ref": "E2:E8", - "categories_ref": "F2:F8" - } - ] - }, - "importance": "edge" - } - ] - } - ] -} From c15a01f2a7eb7de949f0b04d19698a985cc8ea61 Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Mon, 7 Sep 2026 23:50:23 -0700 Subject: [PATCH 08/11] test(harness): cover env-independent calc/mutation/zavora contracts Adds 28 contract tests for paths CI can execute without LibreOffice, aspose-cells-foss, or the Rust helper: strict calc-tier status semantics with synthetic engines, expected-payload validation, cache-free fixture invariants, engine-unavailable reporting, mutation-suite control flow (unavailable/failed/integrity/passed rows, repeats guard, manifest parsing, time-output parsing, package integrity helpers), modifiable engine guards, mutation-report verdict branches, and Zavora adapter payload/error contracts. Harness fixes the tests exposed: - run_calc_suite now contains engine exceptions as failed rows instead of aborting the suite - LibreOfficeCalcEngine reports unavailable (not failed) when the binary is missing Verification: ruff clean; mypy 0 issues in 150 files; full suite 1263 passed, 79 skipped, 6 xfailed. --- src/excelbench/harness/calc.py | 19 +- tests/test_env_fallback_contracts.py | 697 +++++++++++++++++++++++++++ 2 files changed, 713 insertions(+), 3 deletions(-) create mode 100644 tests/test_env_fallback_contracts.py diff --git a/src/excelbench/harness/calc.py b/src/excelbench/harness/calc.py index 65d0d86..69250e6 100644 --- a/src/excelbench/harness/calc.py +++ b/src/excelbench/harness/calc.py @@ -196,6 +196,12 @@ def available(self) -> bool: def calculate(self, input_path: Path, output_path: Path) -> dict[str, Any]: """Calculate with LibreOffice and read cached results from its output.""" + if not self.available(): + return { + "status": "unavailable", + "values": {}, + "reason": f"LibreOffice binary not found at {SOFFICE_PATH}", + } reason = recalculate_with_libreoffice(input_path, output_path) if reason is not None: return {"status": "failed", "values": {}, "reason": reason} @@ -361,9 +367,16 @@ def run_calc_suite( "reason": f"{engine.name} is unavailable", } continue - engine_result = engine.calculate( - fixture, output_dir / engine.name / fixture.name - ) + try: + engine_result = engine.calculate( + fixture, output_dir / engine.name / fixture.name + ) + except Exception as exc: # Engine crashes are comparison data, not aborts. + engine_result = { + "status": "failed", + "values": {}, + "reason": f"{type(exc).__name__}: {exc}", + } values = engine_result.get("values", {}) if not isinstance(values, Mapping): values = {} diff --git a/tests/test_env_fallback_contracts.py b/tests/test_env_fallback_contracts.py new file mode 100644 index 0000000..7efe564 --- /dev/null +++ b/tests/test_env_fallback_contracts.py @@ -0,0 +1,697 @@ +"""Env-independent contracts for optional-dependency harness paths. + +Covers calc-tier status semantics, mutation-suite control flow, modifiable +engine guards, renderers, and the Zavora adapter's payload/error paths on +machines without LibreOffice, aspose-cells-foss, or the Rust helper. +""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path +from typing import Any + +import openpyxl +import pytest + +from excelbench import modifiable as modifiable_module +from excelbench.harness import calc as calc_module +from excelbench.harness import mutation as mutation_module +from excelbench.harness.adapters import zavora_adapter as zavora_module +from excelbench.harness.adapters.zavora_adapter import ZavoraAdapter +from excelbench.harness.calc import ( + AsposeCellsFossCalcEngine, + LibreOfficeCalcEngine, + ZavoraCalcEngine, + formula_cells, + run_calc_suite, +) +from excelbench.models import CellType, CellValue +from excelbench.modifiable import OpenpyxlEngine, _mutation_target +from excelbench.results.mutation_renderer import render_mutation_report + +REPO_ROOT = Path(__file__).resolve().parents[1] +FIXTURE = REPO_ROOT / "fixtures" / "calc" / "financial_model.xlsx" + + +class _FakeEngine: + def __init__( + self, + name: str, + available: bool = True, + status: str = "passed", + values: dict[str, Any] | None = None, + reason: str | None = None, + raises: Exception | None = None, + ) -> None: + self.name = name + self._available = available + self._status = status + self._values = values or {} + self._reason = reason + self._raises = raises + + def available(self) -> bool: + return self._available + + def calculate(self, input_path: Path, output_path: Path) -> dict[str, Any]: + if self._raises is not None: + raise self._raises + return {"status": self._status, "values": self._values, "reason": self._reason} + + +def _expected(cells: dict[str, Any]) -> dict[str, Any]: + return {"oracle": "test-oracle", "cells": cells} + + +def _cell(value: Any, cell_type: str = "number") -> dict[str, Any]: + return {"value": value, "type": cell_type} + + +# -------------------------------------------------------------------------- +# Calc-tier status semantics +# -------------------------------------------------------------------------- + + +def test_calc_suite_marks_partial_match_failed_with_missing_wrong_split( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + values = { + "Sheet1!A1": 1, + "Sheet1!A2": None, + "Sheet1!A3": 99, + } + monkeypatch.setattr( + calc_module, "_engines", lambda: (_FakeEngine("partial", values=values),) + ) + results = run_calc_suite( + FIXTURE, + _expected( + { + "Sheet1!A1": _cell(1), + "Sheet1!A2": _cell(2), + "Sheet1!A3": _cell(3), + "Sheet1!A4": _cell(4), + } + ), + tmp_path, + ) + engine = results["engines"]["partial"] + assert engine["status"] == "failed" + assert engine["matched"] == 1 + assert engine["total"] == 4 + assert "3/4 formula values wrong or missing" in engine["reason"] + assert "2 missing" in engine["reason"] + assert "1 wrong" in engine["reason"] + + +def test_calc_suite_full_match_passes_and_renders( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr( + calc_module, + "_engines", + lambda: ( + _FakeEngine("good", values={"Sheet1!A1": 10}), + _FakeEngine("bad", status="failed", values={}, reason="exploded"), + _FakeEngine( + "absent", + available=False, + values={"Sheet1!A1": 10}, + ), + ), + ) + results = run_calc_suite(FIXTURE, _expected({"Sheet1!A1": _cell(10)}), tmp_path) + assert results["oracle"] == "test-oracle" + assert results["engines"]["good"]["status"] == "passed" + assert results["engines"]["good"]["reason"] is None + assert results["engines"]["bad"]["status"] == "failed" + assert results["engines"]["bad"]["reason"] == "exploded" + assert results["engines"]["absent"]["status"] == "unavailable" + assert results["engines"]["absent"]["reason"] == "absent is unavailable" + + rendered = json.loads((tmp_path / "results.json").read_text()) + assert set(rendered["engines"]) == {"good", "bad", "absent"} + readme = (tmp_path / "README.md").read_text() + assert "good" in readme and "unavailable" in readme.lower() + + +def test_calc_suite_values_must_be_mapping( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + class _ListValuesEngine(_FakeEngine): + def calculate(self, input_path: Path, output_path: Path) -> dict[str, Any]: + result = super().calculate(input_path, output_path) + result["values"] = ["not", "a", "mapping"] + return result + + monkeypatch.setattr(calc_module, "_engines", lambda: (_ListValuesEngine("listy"),)) + results = run_calc_suite(FIXTURE, _expected({"A1": _cell(1)}), tmp_path) + assert results["engines"]["listy"]["status"] == "failed" + assert results["engines"]["listy"]["matched"] == 0 + + +def test_calc_suite_rejects_malformed_expected_payloads(tmp_path: Path) -> None: + with pytest.raises(ValueError, match="cells mapping"): + run_calc_suite(FIXTURE, {"oracle": "x", "cells": [1, 2]}, tmp_path) + with pytest.raises(ValueError, match="has no value"): + run_calc_suite(FIXTURE, _expected({"A1": {"type": "number"}}), tmp_path) + + +def test_calc_suite_engine_exception_is_contained( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr( + calc_module, + "_engines", + lambda: (_FakeEngine("boom", raises=RuntimeError("kaput")),), + ) + results = run_calc_suite(FIXTURE, _expected({"A1": _cell(1)}), tmp_path) + assert results["engines"]["boom"]["status"] == "failed" + + +# -------------------------------------------------------------------------- +# Calc helper contracts +# -------------------------------------------------------------------------- + + +def test_load_expected_accepts_dict_file_and_dir(tmp_path: Path) -> None: + payload = {"oracle": "o", "cells": {"A1": _cell(1)}} + assert calc_module._load_expected(payload) is payload + + file_path = tmp_path / "custom.json" + file_path.write_text(json.dumps(payload)) + assert calc_module._load_expected(file_path) == payload + + (tmp_path / "expected_values.json").write_text(json.dumps(payload)) + assert calc_module._load_expected(tmp_path) == payload + + +def test_committed_calc_fixture_is_formula_dense_and_cache_free() -> None: + references = formula_cells(FIXTURE) + assert len(references) == 133 + + cached = calc_module._read_values(FIXTURE, references[:10], reader="openpyxl") + assert set(cached.values()) == {None} + + +def test_libreoffice_engine_reports_missing_binary( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr(calc_module, "SOFFICE_PATH", Path("/nonexistent/soffice")) + engine = LibreOfficeCalcEngine() + assert engine.available() is False + result = engine.calculate(FIXTURE, tmp_path / "out.xlsx") + assert result["status"] == "unavailable" + assert "not found" in result["reason"] + + reason = calc_module.recalculate_with_libreoffice(FIXTURE, tmp_path / "out.xlsx") + assert reason is not None and "not found" in reason + + +def test_aspose_calc_engine_unavailable_without_package( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setitem(sys.modules, "aspose", None) + assert AsposeCellsFossCalcEngine().available() is False + + +def _fake_oracle_catalog(available: bool) -> Any: + class _Tool: + def is_available(self) -> bool: + return available + + class _Catalog: + def __call__(self, repo_root: Path | None = None) -> dict[str, Any]: + return {"zavora": _Tool()} + + return _Catalog() + + +def test_zavora_calc_engine_unavailable_without_helper( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr( + calc_module, "external_oracle_catalog", _fake_oracle_catalog(False) + ) + engine = ZavoraCalcEngine() + assert engine.available() is False + result = engine.calculate(FIXTURE, tmp_path / "out.xlsx") + assert result["status"] == "unavailable" + assert result["reason"] == "Zavora helper is unavailable" + + +# -------------------------------------------------------------------------- +# Mutation-suite control flow +# -------------------------------------------------------------------------- + + +def _write_template_with_manifest(directory: Path) -> Path: + template = directory / "template.xlsx" + workbook = openpyxl.Workbook() + sheet = workbook.active + assert sheet is not None + sheet.title = "Inputs" + sheet["A1"] = "original" + sheet["B1"] = 1 + workbook.save(template) + manifest = { + "mutation": {"sheet": "Inputs", "cell": "A1", "value": "-landed"}, + "second_mutation": {"sheet": "Inputs", "cell": "B1", "value": 42}, + } + (directory / "manifest.json").write_text(json.dumps(manifest)) + return template + + +class _UnavailableEngine: + name = "ghost" + + def available(self) -> bool: + return False + + def mutate( + self, template: Path, output: Path, mutations: list[dict[str, Any]] + ) -> None: + raise AssertionError("unavailable engines must not run") + + +def test_run_mutation_suite_rejects_zero_repeats(tmp_path: Path) -> None: + template = _write_template_with_manifest(tmp_path) + with pytest.raises(ValueError, match="at least 1"): + mutation_module.run_mutation_suite(template, tmp_path / "out", repeats=0) + + +def test_run_mutation_suite_unavailable_engine_row(tmp_path: Path) -> None: + template = _write_template_with_manifest(tmp_path) + monkey = pytest.MonkeyPatch() + monkey.setattr( + mutation_module, "modifiable_engines", lambda: [_UnavailableEngine()] + ) + try: + results = mutation_module.run_mutation_suite( + template, tmp_path / "out", repeats=1 + ) + finally: + monkey.undo() + row = results["engines"]["ghost"] + assert row["status"] == "unavailable" + assert row["available"] is False + assert row["wall_ms_median"] is None + + +def test_run_mutation_suite_reports_failed_engine( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + template = _write_template_with_manifest(tmp_path) + + def _explode( + engine: Any, + template: Path, + output: Path, + mutations: list[dict[str, Any]], + ) -> tuple[float, float]: + raise RuntimeError("driver crashed") + + monkeypatch.setattr(mutation_module, "_run_subprocess_mutation", _explode) + monkeypatch.setattr( + mutation_module, + "modifiable_engines", + lambda: [_UnavailableEngine.__new__(_UnavailableEngine)], # noqa: E501 + ) + + class _LiveEngine(_UnavailableEngine): + name = "live" + + def available(self) -> bool: + return True + + monkeypatch.setattr(mutation_module, "modifiable_engines", lambda: [_LiveEngine()]) + results = mutation_module.run_mutation_suite(template, tmp_path / "out", repeats=1) + row = results["engines"]["live"] + assert row["status"] == "failed" + assert "driver crashed" in row["details"]["error"] + assert row["preservation_score"] is None + + +def test_run_mutation_suite_passes_when_mutations_land( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + template = _write_template_with_manifest(tmp_path) + + def _apply( + engine: Any, + template: Path, + output: Path, + mutations: list[dict[str, Any]], + ) -> tuple[float, float]: + workbook = openpyxl.load_workbook(template) + try: + for mutation in mutations: + sheet = workbook[str(mutation["sheet"])] + sheet[str(mutation["cell"])] = mutation["value"] + workbook.save(output) + finally: + workbook.close() + return 12.5, 2048.0 + + monkeypatch.setattr(mutation_module, "_run_subprocess_mutation", _apply) + + class _ApplyingEngine(_UnavailableEngine): + name = "applying" + + def available(self) -> bool: + return True + + monkeypatch.setattr( + mutation_module, "modifiable_engines", lambda: [_ApplyingEngine()] + ) + results = mutation_module.run_mutation_suite(template, tmp_path / "out", repeats=2) + row = results["engines"]["applying"] + assert row["status"] == "passed" + assert row["wall_ms_median"] == 12.5 + assert row["peak_rss_kb_median"] == 2048.0 + assert row["preservation_score"] == 100.0 + assert row["details"]["mutations_landed"] is True + + +def test_run_mutation_suite_flags_integrity_when_values_do_not_land( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + template = _write_template_with_manifest(tmp_path) + + def _copy_only( + engine: Any, + template: Path, + output: Path, + mutations: list[dict[str, Any]], + ) -> tuple[float, float]: + import shutil + + shutil.copyfile(template, output) + return 5.0, 1024.0 + + monkeypatch.setattr(mutation_module, "_run_subprocess_mutation", _copy_only) + + class _LazyEngine(_UnavailableEngine): + name = "lazy" + + def available(self) -> bool: + return True + + monkeypatch.setattr(mutation_module, "modifiable_engines", lambda: [_LazyEngine()]) + results = mutation_module.run_mutation_suite(template, tmp_path / "out", repeats=1) + row = results["engines"]["lazy"] + assert row["status"] == "integrity-failed" + assert row["preservation_score"] == 0.0 + assert "did not match" in row["details"]["integrity_failure"] + + +def test_mutations_for_engine_substitutes_placeholder() -> None: + manifest = { + "mutation": {"sheet": "S", "cell": "A1", "value": "-v"}, + "second_mutation": {"sheet": "S", "cell": "B1", "value": 7}, + } + mutations = mutation_module._mutations_for_engine(manifest, "wolfxl") + assert mutations[0]["value"] == "wolfxl-v" + assert mutations[1] == {"sheet": "S", "cell": "B1", "value": 7} + + +def test_mutations_landed_rejects_unreadable_output(tmp_path: Path) -> None: + bogus = tmp_path / "bogus.xlsx" + bogus.write_bytes(b"not an xlsx") + mutations = [{"sheet": "S", "cell": "A1", "value": 1}] + assert mutation_module._mutations_landed(bogus, mutations) is False + + +def test_parse_time_output_extracts_elapsed_and_rss() -> None: + stderr = "\n".join( + [ + " 0.05 real", + " 0.04 user", + " 0.01 sys", + " 4194304 maximum resident set size", + ] + ) + elapsed, rss = mutation_module._parse_time_output(stderr) + assert elapsed == 0.05 + assert rss == 4096.0 + + elapsed_none, rss_none = mutation_module._parse_time_output("garbage") + assert elapsed_none is None and rss_none is None + + +def test_package_integrity_helpers_flag_damage() -> None: + rels_ns = "http://schemas.openxmlformats.org/package/2006/relationships" + parts = { + "xl/_rels/workbook.xml.rels": ( + '' + ).encode(), + "xl/workbook.xml": b"", + "[Content_Types].xml": ( + b'' + ), + } + dangling = mutation_module._dangling_relationships(parts) + assert dangling == ["xl/_rels/workbook.xml.rels: xl/worksheets/sheet1.xml"] + + # workbook.xml has neither an Override nor an xml Default declaration. + missing = mutation_module._missing_content_types(parts) + assert "xl/workbook.xml" in missing + + absent_types = mutation_module._missing_content_types( + {"xl/workbook.xml": b""} + ) + assert absent_types == ["[Content_Types].xml"] + + resolved = mutation_module._relationship_target( + "xl/_rels/x.rels", "worksheets/s.xml" + ) + assert resolved == "xl/worksheets/s.xml" + worksheet_ns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main" + present = f''.encode() + assert mutation_module._xml_has_element(present, "b") is True + assert mutation_module._xml_has_element(b"", "b") is False + assert mutation_module._xml_has_element(b"not xml <", "b") is False + + +# -------------------------------------------------------------------------- +# Modifiable engine guards +# -------------------------------------------------------------------------- + + +def test_mutation_target_splits_sheet_cell_value() -> None: + sheet, cell, value = _mutation_target({"sheet": "Inputs", "cell": "A1", "value": 5}) + assert (sheet, cell, value) == ("Inputs", "A1", 5) + + +def test_openpyxl_engine_mutates_template(tmp_path: Path) -> None: + template = _write_template_with_manifest(tmp_path) + engine = OpenpyxlEngine() + assert engine.available() is True + output = tmp_path / "mutated.xlsx" + engine.mutate( + template, + output, + [ + {"sheet": "Inputs", "cell": "A1", "value": "changed"}, + {"sheet": "Inputs", "cell": "B1", "value": 9}, + ], + ) + workbook = openpyxl.load_workbook(output) + try: + assert workbook["Inputs"]["A1"].value == "changed" + assert workbook["Inputs"]["B1"].value == 9 + finally: + workbook.close() + + +def test_optional_engines_report_absence(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr(modifiable_module, "_aspose_cells_foss", None) + engine = modifiable_module.AsposeFossEngine() + assert engine.available() is False + with pytest.raises(RuntimeError, match="not installed"): + engine.mutate(Path("t.xlsx"), Path("o.xlsx"), []) + + monkeypatch.setattr( + modifiable_module, "external_oracle_catalog", _fake_oracle_catalog(False) + ) + assert modifiable_module.ZavoraEngine().available() is False + + +# -------------------------------------------------------------------------- +# Renderers +# -------------------------------------------------------------------------- + + +def test_mutation_report_renders_all_verdict_branches(tmp_path: Path) -> None: + results: dict[str, Any] = { + "metadata": {"template_sha256": "abc", "repeats": 1, "platform": "Darwin"}, + "engines": { + "perfect": { + "available": True, + "status": "passed", + "wall_ms_median": 100.0, + "peak_rss_kb_median": 2048.0, + "preservation_score": 100.0, + "details": {}, + }, + "lossy": { + "available": True, + "status": "passed", + "wall_ms_median": 200.0, + "peak_rss_kb_median": 4096.0, + "preservation_score": 60.0, + "details": {}, + }, + "broken": { + "available": True, + "status": "integrity-failed", + "wall_ms_median": 300.0, + "peak_rss_kb_median": None, + "preservation_score": 0.0, + "details": {"integrity_failure": "nope"}, + }, + "crashed": { + "available": True, + "status": "failed", + "wall_ms_median": None, + "peak_rss_kb_median": None, + "preservation_score": None, + "details": {"error": "RuntimeError: x"}, + }, + "ghost": { + "available": False, + "status": "unavailable", + "wall_ms_median": None, + "peak_rss_kb_median": None, + "preservation_score": None, + "details": {}, + }, + }, + } + render_mutation_report(results, tmp_path) + persisted: dict[str, Any] = json.loads((tmp_path / "results.json").read_text()) + engines = persisted["engines"] + assert isinstance(engines, dict) + assert set(engines) == set(results["engines"]) + + readme = (tmp_path / "README.md").read_text() + for marker in ("Preserved", "Loss detected", "Mutation integrity failed", "Failed"): + assert marker in readme, marker + + +# -------------------------------------------------------------------------- +# Zavora adapter payload and failure contracts +# -------------------------------------------------------------------------- + + +def test_zavora_adapter_reports_unavailable_helper( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setattr( + zavora_module, "external_oracle_catalog", _fake_oracle_catalog(False) + ) + assert ZavoraAdapter.is_available() is False + + +def _fake_oracle_result( + *, skipped: bool = False, passed: bool = False, payload: Any = None +) -> Any: + class _Result: + def __init__(self) -> None: + self.skipped = skipped + self.passed = passed + self.payload = payload if isinstance(payload, dict) else {} + self.notes = "helper skipped" if skipped else None + self.stderr = "" + self.stdout = "" + + return _Result() + + +def test_zavora_save_raises_when_helper_skips_or_fails( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + adapter = ZavoraAdapter() + monkeypatch.setattr( + zavora_module, + "run_external_oracle", + lambda *a, **k: _fake_oracle_result(skipped=True), + ) + with pytest.raises(FileNotFoundError, match="helper skipped"): + adapter.save_workbook({"sheets": []}, tmp_path / "out.xlsx") + + monkeypatch.setattr( + zavora_module, + "run_external_oracle", + lambda *a, **k: _fake_oracle_result( + passed=False, payload={"message": "rust panic"} + ), + ) + with pytest.raises(RuntimeError, match="rust panic"): + adapter.save_workbook({"sheets": []}, tmp_path / "out.xlsx") + + +def test_zavora_write_cell_value_payload_variants() -> None: + adapter = ZavoraAdapter() + workbook = adapter.create_workbook() + adapter.write_cell_value( + workbook, "S", "A1", CellValue(type=CellType.FORMULA, value=0, formula="=1+1") + ) + adapter.write_cell_value( + workbook, "S", "A2", CellValue(type=CellType.STRING, value="") + ) + adapter.write_cell_value( + workbook, "S", "A3", CellValue(type=CellType.NUMBER, value=7) + ) + assert workbook["cells"][0] == { + "sheet": "S", + "cell": "A1", + "type": "formula", + "formula": "=1+1", + "value": 0, + } + assert workbook["cells"][1]["type"] == "blank" + assert workbook["cells"][1]["value"] is None + assert workbook["cells"][2] == { + "sheet": "S", + "cell": "A3", + "type": str(CellType.NUMBER), + "value": 7, + } + assert {"name": "S"} in workbook["sheets"] + + +def test_zavora_conditional_format_mapping_helpers() -> None: + adapter = ZavoraAdapter() + assert adapter._map_conditional_format_type("colorScale") == "3_color_scale" + assert adapter._map_conditional_format_type("dataBar") == "data_bar" + assert adapter._map_conditional_format_type("expression") == "formula" + assert adapter._map_conditional_format_type("cellIs") == "cell" + assert ( + adapter._map_conditional_format_criteria("expression", None, "=Ref!$A$1>0") + == "Ref!$A$1>0" + ) + assert ( + adapter._map_conditional_format_criteria("cellIs", "greaterThan", None) == ">" + ) + assert ( + adapter._map_conditional_format_criteria("cellIs", "unknownOperator", None) + == ">" + ) + + +def test_zavora_read_operations_raise_structured_unsupported() -> None: + adapter = ZavoraAdapter() + workbook = adapter.create_workbook() + with pytest.raises(NotImplementedError, match="write-only"): + adapter.read_cell_value(workbook, "S", "A1") + with pytest.raises(NotImplementedError, match="write-only"): + adapter.get_sheet_names(workbook) From 0c841194b3dc6bccefe30f3a73fc749ebdd2a0f2 Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Tue, 8 Sep 2026 00:05:15 -0700 Subject: [PATCH 09/11] test(adapters): cover wolfxl adapter round-trip contracts Adds seven round-trip tests exercising WolfxlAdapter through the public WolfXL API: value/boolean/blank round-trips, source-path bookkeeping, format/border/dimension/merge, formula, hyperlink, and structural features (freeze panes, named ranges, comments, tables). All operations verified identical on WolfXL 2.0.1 (PyPI) and 2.1.0 (local wheel), so the tests run ungated in CI. Adapter coverage: 1% -> 45% (261 of 586 statements). Verification: ruff clean; mypy 0 issues; full suite 1270 passed, 79 skipped, 6 xfailed; every test re-run against wolfxl 2.0.1 in a throwaway venv. --- tests/test_wolfxl_adapter_roundtrip.py | 211 +++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 tests/test_wolfxl_adapter_roundtrip.py diff --git a/tests/test_wolfxl_adapter_roundtrip.py b/tests/test_wolfxl_adapter_roundtrip.py new file mode 100644 index 0000000..7df91cd --- /dev/null +++ b/tests/test_wolfxl_adapter_roundtrip.py @@ -0,0 +1,211 @@ +"""Round-trip contracts for the WolfxlAdapter through the public WolfXL API. + +Verified against WolfXL 2.0.1 (PyPI) and 2.1.0 (local wheel): every +covered operation behaves identically on both versions. +""" + +from __future__ import annotations + +from pathlib import Path +from typing import Any + +import pytest + +wolfxl = pytest.importorskip("wolfxl", reason="wolfxl not installed") + +from excelbench.harness.adapters import WolfxlAdapter # noqa: E402 +from excelbench.models import ( # noqa: E402 + BorderEdge, + BorderInfo, + BorderStyle, + CellFormat, + CellType, + CellValue, +) + + +@pytest.fixture +def adapter() -> Any: + assert WolfxlAdapter is not None + return WolfxlAdapter() + + +def _string(value: str) -> CellValue: + return CellValue(type=CellType.STRING, value=value) + + +def _number(value: float) -> CellValue: + return CellValue(type=CellType.NUMBER, value=value) + + +def _build_basic_workbook(adapter: Any) -> Any: + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "Data") + adapter.write_cell_value(workbook, "Data", "A1", _string("hello")) + adapter.write_cell_value(workbook, "Data", "B1", _number(7)) + adapter.write_cell_value(workbook, "Data", "B2", _number(2.5)) + return workbook + + +def test_value_round_trip(adapter: Any, tmp_path: Path) -> None: + workbook = _build_basic_workbook(adapter) + path = tmp_path / "values.xlsx" + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + try: + assert adapter.get_sheet_names(reopened) == ["Data"] + assert adapter.read_cell_value(reopened, "Data", "A1").value == "hello" + assert adapter.read_cell_value(reopened, "Data", "B1").value == 7 + assert adapter.read_cell_value(reopened, "Data", "B2").value == 2.5 + finally: + adapter.close_workbook(reopened) + + +def test_boolean_and_blank_round_trip(adapter: Any, tmp_path: Path) -> None: + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "S") + adapter.write_cell_value( + workbook, "S", "A1", CellValue(type=CellType.BOOLEAN, value=True) + ) + adapter.write_cell_value( + workbook, "S", "A2", CellValue(type=CellType.BLANK, value=None) + ) + path = tmp_path / "bool.xlsx" + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + try: + assert adapter.read_cell_value(reopened, "S", "A1").value is True + assert adapter.read_cell_value(reopened, "S", "A2").value is None + finally: + adapter.close_workbook(reopened) + + +def test_opened_workbook_tracks_its_source_path(adapter: Any, tmp_path: Path) -> None: + workbook = _build_basic_workbook(adapter) + path = tmp_path / "bound.xlsx" + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + try: + assert adapter._workbook_paths.get(id(reopened)) == path + finally: + adapter.close_workbook(reopened) + + +def test_format_border_dimension_merge_round_trip(adapter: Any, tmp_path: Path) -> None: + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "F") + adapter.write_cell_value(workbook, "F", "A1", _number(1)) + adapter.write_cell_format( + workbook, + "F", + "A1", + CellFormat(bold=True, font_size=14.0, bg_color="#FFFF0000"), + ) + adapter.write_cell_border( + workbook, + "F", + "A1", + BorderInfo(bottom=BorderEdge(style=BorderStyle.MEDIUM, color="#FF0000")), + ) + adapter.set_row_height(workbook, "F", 1, 30.5) + adapter.set_column_width(workbook, "F", "A", 42.0) + adapter.merge_cells(workbook, "F", "A3:B4") + path = tmp_path / "formatted.xlsx" + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + try: + cell_format = adapter.read_cell_format(reopened, "F", "A1") + assert cell_format.bold is True + assert cell_format.font_size == 14.0 + + border = adapter.read_cell_border(reopened, "F", "A1") + assert border.bottom is not None + assert border.bottom.style == BorderStyle.MEDIUM + + assert adapter.read_row_height(reopened, "F", 1) == 30.5 + assert adapter.read_column_width(reopened, "F", "A") == 42.0 + assert "A3:B4" in adapter.read_merged_ranges(reopened, "F") + finally: + adapter.close_workbook(reopened) + + +def test_formula_text_round_trip(adapter: Any, tmp_path: Path) -> None: + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "C") + adapter.write_cell_value(workbook, "C", "A1", _number(2)) + adapter.write_cell_value(workbook, "C", "A2", _number(3)) + adapter.write_cell_value( + workbook, + "C", + "A3", + CellValue(type=CellType.FORMULA, value=5, formula="=A1+A2"), + ) + path = tmp_path / "formula.xlsx" + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + try: + formula_cell = adapter.read_cell_value(reopened, "C", "A3") + assert formula_cell.formula == "=A1+A2" + finally: + adapter.close_workbook(reopened) + + +def test_structure_round_trip(adapter: Any, tmp_path: Path) -> None: + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "S") + adapter.write_cell_value(workbook, "S", "B2", _number(42)) + adapter.set_freeze_panes(workbook, "S", {"mode": "freeze", "top_left_cell": "B2"}) + adapter.add_named_range( + workbook, "S", {"name": "SingleCell", "refers_to": "S!$B$2"} + ) + adapter.add_comment( + workbook, "S", {"cell": "A2", "text": "note", "author": "tester"} + ) + adapter.add_table(workbook, "S", {"name": "T1", "ref": "A1:A2"}) + path = tmp_path / "structure.xlsx" + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + try: + assert adapter.read_freeze_panes(reopened, "S") == { + "mode": "freeze", + "top_left_cell": "B2", + } + ranges = adapter.read_named_ranges(reopened, "S") + assert any(item["name"] == "SingleCell" for item in ranges) + comments = adapter.read_comments(reopened, "S") + assert comments[0]["text"] == "note" + tables = adapter.read_tables(reopened, "S") + assert tables[0]["name"] == "T1" + finally: + adapter.close_workbook(reopened) + + +def test_hyperlink_round_trip(adapter: Any, tmp_path: Path) -> None: + workbook = adapter.create_workbook() + adapter.add_sheet(workbook, "L") + adapter.write_cell_value(workbook, "L", "A1", _string("site")) + adapter.add_hyperlink( + workbook, + "L", + { + "cell": "A1", + "target": "https://example.com", + "display": "Example", + "internal": False, + }, + ) + path = tmp_path / "links.xlsx" + adapter.save_workbook(workbook, path) + + reopened = adapter.open_workbook(path) + try: + links = adapter.read_hyperlinks(reopened, "L") + assert any(link.get("target") == "https://example.com" for link in links) + finally: + adapter.close_workbook(reopened) From 4c7bb0156d6b1eb1d35e202a661e389f25a01a22 Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Tue, 8 Sep 2026 00:16:12 -0700 Subject: [PATCH 10/11] ci(test): install rust and aspose engine extras The test job previously installed only the dev extra, so wolfxl and aspose-cells-foss were absent on CI: the wolfxl adapter tests skipped and roughly a thousand adapter statements could never count toward coverage, pinning the suite at 63.8% against the 65% gate. Both extras are pure installs from PyPI (wolfxl 2.0.1 wheel, aspose-cells-foss py3-none-any wheel). Verified in a CI-parity venv (python 3.12, wolfxl 2.0.1, aspose-cells-foss 26.7.0, no soffice): 1270 passed, 79 skipped, 6 xfailed, exact coverage 66.43%. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c96a7f..3c1e2b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: python-version: ${{ matrix.python-version }} - uses: astral-sh/setup-uv@v3 - name: Install deps - run: uv sync --extra dev + run: uv sync --extra dev --extra rust --extra aspose - name: Unit tests with coverage run: > uv run pytest From 15b897e22359d4188fe9eb123e25bc4b4512dad2 Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Tue, 8 Sep 2026 00:22:01 -0700 Subject: [PATCH 11/11] fix(ci): upgrade locked wolfxl to 2.0.1 for engine extras The test job's new rust extra resolved to the lock's ancient wolfxl 0.1.0, whose Workbook lacks the remove() API the adapter and its round-trip tests rely on. Upgrades the single lock entry to 2.0.1 (plus its new defusedxml dependency); no other packages change. Verified in a venv synced exactly from the updated lock (python 3.12, wolfxl 2.0.1, aspose-cells-foss, no soffice): 1270 passed, 79 skipped, 6 xfailed, exact coverage 66.31%. --- uv.lock | 53 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/uv.lock b/uv.lock index cd1b5ef..5c55156 100644 --- a/uv.lock +++ b/uv.lock @@ -375,6 +375,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, ] +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + [[package]] name = "et-xmlfile" version = "2.0.0" @@ -2107,19 +2116,39 @@ wheels = [ [[package]] name = "wolfxl" -version = "0.1.0" +version = "2.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/25/df/775d22632067cfeb408a1621930e5b3a8adff8b6497cd780b9565b8bc4a4/wolfxl-0.1.0.tar.gz", hash = "sha256:24bafc7891161b036bd2482b5c30d1b46607155f45b0cdadecd0cb821d9959dc", size = 101351, upload-time = "2026-02-16T06:56:58.838Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/98/477238e547f18f2a221ed7ac496d84a5565b4d406a808a950be297a18f84/wolfxl-0.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3eda40a4214e89b5bdd6cb79a9b1ef7535f562d9ae7e04b8c2e12eb557bdee7", size = 1704813, upload-time = "2026-02-16T06:56:41.036Z" }, - { url = "https://files.pythonhosted.org/packages/52/df/02bbbe841ceea7af0d50ef709d4f72bed91800799bcf0036bbda53092391/wolfxl-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1253d276e069210de7341956c58ef7f2bd021d336f01f94ef86ab01e06ff7c1", size = 1755972, upload-time = "2026-02-16T06:56:43.045Z" }, - { url = "https://files.pythonhosted.org/packages/d3/9c/1214cca9b121ee7ca491fb40cbed4e93e220c734e661d854f77be3521786/wolfxl-0.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ab24eb6d732be42ded39d09ce8ef24feeff5a86730c56c652a1d25d245261fc6", size = 1662399, upload-time = "2026-02-16T06:56:44.991Z" }, - { url = "https://files.pythonhosted.org/packages/b2/44/b2ffb8b4c32ab9ce952f0dbc36b41cf187acde9fe42687e597f33e381128/wolfxl-0.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0af64fc84b2cc68463f646f3785d1caa00c9b92497d19e0a425110255a6f07ab", size = 1598530, upload-time = "2026-02-16T06:56:46.801Z" }, - { url = "https://files.pythonhosted.org/packages/64/2c/cf0a39ec9e15229fc0b3486ebcef81cd71c71321d0c8c63e7924006d34e8/wolfxl-0.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c51a55c1302d11291f918482c7995a1ad3a572daece73cbefb1e40e6aa902c8", size = 1705644, upload-time = "2026-02-16T06:56:48.408Z" }, - { url = "https://files.pythonhosted.org/packages/18/ca/1fa161476bc9d599515357e64a911c519533947b40248d3109229f9379d5/wolfxl-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c16c93dcae0664ecc8a655917d392c241892754a2557d12d493e14c4306e6f45", size = 1757542, upload-time = "2026-02-16T06:56:49.88Z" }, - { url = "https://files.pythonhosted.org/packages/0e/e0/01ba17ee89bf0fec763d1869112a29a37127953bb3abef07e4588c8b989c/wolfxl-0.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:d90fc4c57a92171c9081cad4ec3490dd25ed53d9d63bb2f00fac94a34cb5ab03", size = 1507448, upload-time = "2026-02-16T06:56:51.211Z" }, - { url = "https://files.pythonhosted.org/packages/86/02/0b9999e1ce359a95f4a7bf76a1409e412a94f6dee82930820981375a179b/wolfxl-0.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ac8a6828ecc6cb5e8fcb9ee5d2596820da43dbaa382df5d95677dc18f2b7f20", size = 1704901, upload-time = "2026-02-16T06:56:53.019Z" }, - { url = "https://files.pythonhosted.org/packages/02/bb/ead2bc97276eb7c4c9b2e718c8f91b0dbb27131ecfc42c93bf3e2f259bba/wolfxl-0.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ac1e7b592bfb223b5bc198d2eac1d3dcb6b5d3181c8be189efaea9c8299f45", size = 1756705, upload-time = "2026-02-16T06:56:54.732Z" }, +dependencies = [ + { name = "defusedxml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/ac/65759994e89287f651a9b5ba599e063e39d7db56b5fcbe709a0937b564f3/wolfxl-2.0.1.tar.gz", hash = "sha256:57d93932457efb0dde3971fdf796a1bec8c6014dc060638459e50e4d7736db13", size = 10530974, upload-time = "2026-08-18T07:30:52.218Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fa/28/cccc32d0a397621f8556938f02db97fea9eed47cbb6ace5879a7d2fc88e6/wolfxl-2.0.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a44a23217f3df45bf7817eba97be5cc190d03718aec0b955b9e30356bd59bcb5", size = 3327589, upload-time = "2026-08-18T07:30:03.937Z" }, + { url = "https://files.pythonhosted.org/packages/e0/89/7a89b3e6b2ea642eec0aff3b4e58c214e580d2580fb2e301b7819346a7b3/wolfxl-2.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8d3da48a1b7ec2f1f7b62d2c0d92100bac37e197aace3c9635ab137a56a8e3ae", size = 3153645, upload-time = "2026-08-18T07:30:05.454Z" }, + { url = "https://files.pythonhosted.org/packages/81/bc/798df1baa83600aefdd8651ca36db0079456489050987889c734e7e56371/wolfxl-2.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:ec77009031fb34c7802278cbc5ca5cd95f79f9b29a9da89ca41b8b509b9d3d87", size = 3232132, upload-time = "2026-08-18T07:30:07.079Z" }, + { url = "https://files.pythonhosted.org/packages/56/c4/5e03becc03814e56d8a765ee51f4a0aeb87c68333c4d9c03bc3ba16774b6/wolfxl-2.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:6996b9e0d94ba25ed07e5a968227005fe5ef418c6c42060093a615d1fe72e309", size = 3364313, upload-time = "2026-08-18T07:30:08.602Z" }, + { url = "https://files.pythonhosted.org/packages/b0/9d/192ff24dd4e035d60a039eaf9af732851174057b430dd731457100bbf7c7/wolfxl-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:717126da60bf77b41b6fe1f2302fbedb9e3543fee5a951beef2a8d07e9f48b43", size = 3374507, upload-time = "2026-08-18T07:30:10.25Z" }, + { url = "https://files.pythonhosted.org/packages/79/c6/9f85c6d0c6f928d694ad2048c81faa394feefc05f0c2979cfc640612d404/wolfxl-2.0.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9461100bc0e979aa1e19b29e405914245221e591ba8628d26ad5b3f1fa38a542", size = 3323795, upload-time = "2026-08-18T07:30:12.026Z" }, + { url = "https://files.pythonhosted.org/packages/73/a9/faa95ecefd9d085b4ea1cfcb1ca1c4f3de20603a1da797c62f7d83fd11a3/wolfxl-2.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d08f2e23e151b9ef51a84cde8bf55f52fa7ad8c67c15b5d1d3c2c713aafa07ae", size = 3151192, upload-time = "2026-08-18T07:30:13.649Z" }, + { url = "https://files.pythonhosted.org/packages/3b/65/6f424e6fadd072ed60c8d644e1c785205e4616e5ab189751500b4aa8e5eb/wolfxl-2.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:128b7a15037a3072b9657a7333f2d5aad18a7aa3e6643856870fc34e42d7632e", size = 3230920, upload-time = "2026-08-18T07:30:15.318Z" }, + { url = "https://files.pythonhosted.org/packages/26/52/a24e280a72561b694b107946bfe3371602dc3e7761542412954ee9dfdab1/wolfxl-2.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:85437f13b5fcb1e4fce5c5c3d21f71db3c18685efd10bcd61be24a1363917f53", size = 3366381, upload-time = "2026-08-18T07:30:17.194Z" }, + { url = "https://files.pythonhosted.org/packages/82/46/8cc977e25c4570494fe0fb436d81f1b6061d729f5f14d6eebe49dfb82e2f/wolfxl-2.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:807d89a4f73f069322e27750f02ee428d27b955ae471a7e420643e612040cf89", size = 3365195, upload-time = "2026-08-18T07:30:18.609Z" }, + { url = "https://files.pythonhosted.org/packages/a5/19/be4cef90586d77b25f85f8e5a5db7aa7743091feea8be0b22fe78fc625cc/wolfxl-2.0.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9092422063ceb1291b958716ad796a37b2df69d19c694fcc57923f44874b3403", size = 3324502, upload-time = "2026-08-18T07:30:20.024Z" }, + { url = "https://files.pythonhosted.org/packages/e7/06/fa126fd43d458ecd83294130ba9a91fa345c7cd35a1f52a7543cd1e10c74/wolfxl-2.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be728fa4e04804a2c365a6cac4950fb7be010a26db44da39cabc504b32c27228", size = 3151284, upload-time = "2026-08-18T07:30:21.508Z" }, + { url = "https://files.pythonhosted.org/packages/85/1a/d129b7d9881c200104eef501b4c0cdb8a44ca53160e2855803c9da3c67fa/wolfxl-2.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:1763e329d994ac0309e1552bf5b19fa9377474130567691a9d4b957b49f51226", size = 3230311, upload-time = "2026-08-18T07:30:22.993Z" }, + { url = "https://files.pythonhosted.org/packages/61/80/1493b3d0e670ccc27a9a82de593e18ba8a8856d09db094fbf27459111c04/wolfxl-2.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:a2f790b2dcf8de66f063d3197827c86fcb57f3817a9408d7c1977b9d4745147c", size = 3365113, upload-time = "2026-08-18T07:30:24.464Z" }, + { url = "https://files.pythonhosted.org/packages/ea/17/f7096c60f62fc4d580facbd8cfcf35ed97ce38b04563166d3d54c1199efb/wolfxl-2.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:aa079bce1ea79d94bbb6b26cbced8a547449d7801d898d46d35a9eaa66378726", size = 3364744, upload-time = "2026-08-18T07:30:25.991Z" }, + { url = "https://files.pythonhosted.org/packages/e0/2e/6cb9ec837327433ddd2c9b9630127accf5656b70ae64d2bb41d96d06700a/wolfxl-2.0.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:dbfde5bfc0450e2455099fcd8eadd80a2260ad378c6f8a98b4fcf33fc12e4d8a", size = 3323781, upload-time = "2026-08-18T07:30:27.373Z" }, + { url = "https://files.pythonhosted.org/packages/14/21/6348295559e4a8e77b27f9f4aecb4838b64fc1b186e5149df08247ad8021/wolfxl-2.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9fd37dddf9c765673533f8afd8a974a737f24d4fd7f9b6c23e05e1d66e989782", size = 3152454, upload-time = "2026-08-18T07:30:28.788Z" }, + { url = "https://files.pythonhosted.org/packages/1f/e5/a37e045e01d30e5ccf90c752b08ede0d5b704dda6eef4bbc0700bc45df43/wolfxl-2.0.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:45007ed29f6dee8ad92bdf9f196efe3c9981ac6ddc54c5176e07de433c98f18f", size = 3231819, upload-time = "2026-08-18T07:30:30.224Z" }, + { url = "https://files.pythonhosted.org/packages/17/a9/b9f7320226704d2929ff219c71abe417703c743b6e74037592df6e860f0b/wolfxl-2.0.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:9ce3124f7db927537fff0d8e61d362cc94313b8285702fbd7203f80a90e6518a", size = 3365061, upload-time = "2026-08-18T07:30:31.63Z" }, + { url = "https://files.pythonhosted.org/packages/70/c9/ca0c1d76b3387dd3e8708ecba63a974bfd3c255f7eaf42108ac37c326df7/wolfxl-2.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:069e1be537b44bf9d003c8fefa721537b1a5478232ec4248378319005aaeff69", size = 3365582, upload-time = "2026-08-18T07:30:33.241Z" }, + { url = "https://files.pythonhosted.org/packages/95/ac/2d95abaa2c00f865fdf60f837db827c011c18fa2cdcc4e2138954d2f2595/wolfxl-2.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:3dc52a0ee9341b20e14f72f57e4e01e44887c1aad43a122380f4cce89739fab0", size = 3236416, upload-time = "2026-08-18T07:30:34.84Z" }, + { url = "https://files.pythonhosted.org/packages/f7/44/5c0e799b855da4f55553e61741fa44b89ed1da489a9bd29fa3fe6dba9ef5/wolfxl-2.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:41fb6ac734d80cbadf904be79ed3e23513a66422dd24026306eb2b6aba63ce40", size = 3375950, upload-time = "2026-08-18T07:30:36.245Z" }, + { url = "https://files.pythonhosted.org/packages/45/ed/81f4fdf0df823af92fdbd512ae52a653b2b56209c7647f7acb4b217c147f/wolfxl-2.0.1-cp315-cp315-manylinux_2_28_x86_64.whl", hash = "sha256:64cf32215c985c13002752939009509ba1b4164904a5bdd7efc39992e7df9904", size = 3365063, upload-time = "2026-08-18T07:30:38.301Z" }, + { url = "https://files.pythonhosted.org/packages/2b/26/7ed7d4aec18e23353957b2237bc5e78e06230fc19dd59a519731b0350e7b/wolfxl-2.0.1-cp315-cp315t-manylinux_2_28_x86_64.whl", hash = "sha256:41daab6e511ec253d0f4a87ffb8d961d9b7fc2e2dde56c2b08633b745be567b9", size = 3375953, upload-time = "2026-08-18T07:30:39.9Z" }, + { url = "https://files.pythonhosted.org/packages/8a/90/de6c1919a57c72125b99332fdad3ded2666600ea6c0a40367a1b845c8d12/wolfxl-2.0.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:370ff2cfa41158a4a0979ca07843241c4a9805f42d9c1f1dae6463358716edb6", size = 3235719, upload-time = "2026-08-18T07:30:48.673Z" }, + { url = "https://files.pythonhosted.org/packages/37/21/79f1e3d0b6bda50b98e417e7b34a98dfcfd29b1720af85dc9eadb632f7f8/wolfxl-2.0.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:07bab6fd6baa29068039c1d87b519f3772ba1a1a3057e95195944051ff11e2bb", size = 3366936, upload-time = "2026-08-18T07:30:50.067Z" }, ] [[package]]