zalos-sheetops 0.4.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zalos_sheetops-0.4.2/.github/workflows/ci.yml +54 -0
- zalos_sheetops-0.4.2/.gitignore +10 -0
- zalos_sheetops-0.4.2/AGENTS.md +64 -0
- zalos_sheetops-0.4.2/LICENSE +21 -0
- zalos_sheetops-0.4.2/PKG-INFO +141 -0
- zalos_sheetops-0.4.2/README.md +126 -0
- zalos_sheetops-0.4.2/docs/architecture-and-references.md +218 -0
- zalos_sheetops-0.4.2/pyproject.toml +43 -0
- zalos_sheetops-0.4.2/scripts/setup-libreoffice +40 -0
- zalos_sheetops-0.4.2/skills/claude/SKILL.md +1 -0
- zalos_sheetops-0.4.2/skills/codex/SKILL.md +80 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/__init__.py +5 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/benchmarks/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/benchmarks/large_xlsx.py +361 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/cli.py +1591 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/command_registry.py +227 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/compare/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/compare/workbooks.py +265 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/contracts.py +32 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/diff/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/diff/tabular.py +204 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/display/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/display/scan.py +309 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/display/widths.py +125 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/display/xlsx_metadata.py +127 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/errors.py +11 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/formulas/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/formulas/scan.py +333 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/formulas/xml_scan.py +324 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/hyperlinks/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/hyperlinks/assertions.py +390 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/io/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/io/cellref.py +141 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/io/headers.py +27 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/io/inspect.py +98 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/io/read_cells.py +231 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/io/read_csv_table.py +45 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/io/read_table.py +240 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/io/search_cells.py +532 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/io/xlsx_xml.py +1654 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/normalize/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/normalize/amounts.py +51 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/normalize/dates.py +25 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/normalize/preview.py +148 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/normalize/text.py +22 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/paths.py +28 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/recalc/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/recalc/libreoffice.py +119 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/reconcile/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/reconcile/exact.py +183 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/runtime/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/runtime/libreoffice.py +130 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/styles/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/styles/assertions.py +253 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/styles/read.py +398 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/styles/xml_assertions.py +372 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/testing.py +43 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/validation/__init__.py +1 -0
- zalos_sheetops-0.4.2/src/zalos_sheetops/validation/workbook.py +451 -0
- zalos_sheetops-0.4.2/tests/fixtures/README.md +9 -0
- zalos_sheetops-0.4.2/tests/fixtures/manifest.json +232 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/calamine/LICENSE +23 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/calamine/formula.issue.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/calamine/shared_formula_bench.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/calamine/shared_formula_simple.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/fastexcel/LICENSE +21 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/fastexcel/div0.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/fastexcel/fixture-changing-header-location.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/fastexcel/fixture-sheets-different-visibilities.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/fastexcel/fixture-single-sheet-duplicated-columns.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/fastexcel/sheet-and-table-with-offset.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/fastexcel/sheet-and-table-with-whitespace.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/openpyxl/LICENSE +23 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/openpyxl/complex-styles.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/openpyxl/empty-with-styles.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/openpyxl/hidden_sheets.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/openpyxl/sample.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsx2csv/LICENSE +19 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsx2csv/datetime.csv +1 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsx2csv/datetime.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsx2csv/empty_row.csv +3 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsx2csv/empty_row.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsx2csv/last-column-empty.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsx2csv/utf8.csv +5 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsx2csv/utf8.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsxwriter/LICENSE +25 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsxwriter/autofit01.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsxwriter/formula_results01.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/fixtures/upstream/xlsxwriter/hyperlink01.xlsx +0 -0
- zalos_sheetops-0.4.2/tests/test_cli_cells_search.py +85 -0
- zalos_sheetops-0.4.2/tests/test_cli_compare.py +141 -0
- zalos_sheetops-0.4.2/tests/test_cli_contracts.py +456 -0
- zalos_sheetops-0.4.2/tests/test_cli_diff.py +370 -0
- zalos_sheetops-0.4.2/tests/test_cli_display_scan.py +136 -0
- zalos_sheetops-0.4.2/tests/test_cli_doctor.py +100 -0
- zalos_sheetops-0.4.2/tests/test_cli_formulas_scan.py +370 -0
- zalos_sheetops-0.4.2/tests/test_cli_help.py +41 -0
- zalos_sheetops-0.4.2/tests/test_cli_hyperlinks_assert.py +190 -0
- zalos_sheetops-0.4.2/tests/test_cli_normalize_preview.py +90 -0
- zalos_sheetops-0.4.2/tests/test_cli_output_format.py +32 -0
- zalos_sheetops-0.4.2/tests/test_cli_read_cells.py +158 -0
- zalos_sheetops-0.4.2/tests/test_cli_read_table.py +513 -0
- zalos_sheetops-0.4.2/tests/test_cli_recalc.py +298 -0
- zalos_sheetops-0.4.2/tests/test_cli_reconcile.py +215 -0
- zalos_sheetops-0.4.2/tests/test_cli_startup.py +99 -0
- zalos_sheetops-0.4.2/tests/test_cli_styles_assert.py +303 -0
- zalos_sheetops-0.4.2/tests/test_cli_styles_read.py +109 -0
- zalos_sheetops-0.4.2/tests/test_cli_validate.py +320 -0
- zalos_sheetops-0.4.2/tests/test_compare_workbooks.py +218 -0
- zalos_sheetops-0.4.2/tests/test_diff_tabular.py +130 -0
- zalos_sheetops-0.4.2/tests/test_display_scan.py +135 -0
- zalos_sheetops-0.4.2/tests/test_display_widths.py +25 -0
- zalos_sheetops-0.4.2/tests/test_fixture_manifest.py +35 -0
- zalos_sheetops-0.4.2/tests/test_formulas_scan.py +420 -0
- zalos_sheetops-0.4.2/tests/test_headers.py +72 -0
- zalos_sheetops-0.4.2/tests/test_hyperlinks_assertions.py +138 -0
- zalos_sheetops-0.4.2/tests/test_inspect.py +624 -0
- zalos_sheetops-0.4.2/tests/test_large_xlsx_benchmark.py +143 -0
- zalos_sheetops-0.4.2/tests/test_libreoffice_runtime.py +91 -0
- zalos_sheetops-0.4.2/tests/test_normalize_amounts.py +32 -0
- zalos_sheetops-0.4.2/tests/test_normalize_dates.py +33 -0
- zalos_sheetops-0.4.2/tests/test_normalize_preview.py +83 -0
- zalos_sheetops-0.4.2/tests/test_package_version.py +7 -0
- zalos_sheetops-0.4.2/tests/test_read_cells.py +225 -0
- zalos_sheetops-0.4.2/tests/test_read_csv_table.py +72 -0
- zalos_sheetops-0.4.2/tests/test_read_table.py +350 -0
- zalos_sheetops-0.4.2/tests/test_recalc.py +271 -0
- zalos_sheetops-0.4.2/tests/test_reconcile_exact.py +122 -0
- zalos_sheetops-0.4.2/tests/test_release_docs.py +20 -0
- zalos_sheetops-0.4.2/tests/test_repo_docs.py +43 -0
- zalos_sheetops-0.4.2/tests/test_search_cells.py +188 -0
- zalos_sheetops-0.4.2/tests/test_skill_docs.py +60 -0
- zalos_sheetops-0.4.2/tests/test_styles_assertions.py +201 -0
- zalos_sheetops-0.4.2/tests/test_styles_read.py +202 -0
- zalos_sheetops-0.4.2/tests/test_validate_workbook.py +441 -0
- zalos_sheetops-0.4.2/uv.lock +132 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
tags: ["v*"]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
inputs:
|
|
10
|
+
publish:
|
|
11
|
+
description: Publish the verified package to PyPI
|
|
12
|
+
type: boolean
|
|
13
|
+
default: false
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
verify:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
23
|
+
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
24
|
+
- run: uv sync --all-groups --locked
|
|
25
|
+
- name: Install rtk shim
|
|
26
|
+
run: |
|
|
27
|
+
mkdir -p "$HOME/.local/bin"
|
|
28
|
+
printf '#!/usr/bin/env bash\nexec "$@"\n' > "$HOME/.local/bin/rtk"
|
|
29
|
+
chmod +x "$HOME/.local/bin/rtk"
|
|
30
|
+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
31
|
+
- run: rtk uv run pytest
|
|
32
|
+
- run: rtk uv run ruff check .
|
|
33
|
+
- run: rtk uv run ruff format --check .
|
|
34
|
+
- run: uv build --no-sources
|
|
35
|
+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
36
|
+
with:
|
|
37
|
+
name: distributions
|
|
38
|
+
path: dist/*
|
|
39
|
+
if-no-files-found: error
|
|
40
|
+
|
|
41
|
+
publish:
|
|
42
|
+
if: github.event_name == 'workflow_dispatch' && inputs.publish && github.ref == 'refs/heads/main'
|
|
43
|
+
needs: verify
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
environment: pypi
|
|
46
|
+
permissions:
|
|
47
|
+
id-token: write
|
|
48
|
+
steps:
|
|
49
|
+
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
50
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
51
|
+
with:
|
|
52
|
+
name: distributions
|
|
53
|
+
path: dist
|
|
54
|
+
- run: uv publish --trusted-publishing always dist/*
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Zalos SheetOps Agent Instructions
|
|
2
|
+
|
|
3
|
+
This repo builds spreadsheet tools that Codex, Claude Code, and other AI agents
|
|
4
|
+
can trust for precise Excel and CSV work.
|
|
5
|
+
|
|
6
|
+
## Non-Negotiable Rules
|
|
7
|
+
|
|
8
|
+
- Use test-driven development for every behavior change.
|
|
9
|
+
- Write the failing test first and verify it fails for the expected reason.
|
|
10
|
+
- Add return type annotations to every function.
|
|
11
|
+
- Use built-in collection types such as `list` and `dict`.
|
|
12
|
+
- Do not add a CLI command without JSON contract tests.
|
|
13
|
+
- Do not silently guess workbook structure.
|
|
14
|
+
- Fail closed with a stable `errorCode` and compact JSON details.
|
|
15
|
+
- Keep output deterministic so agents can parse it safely.
|
|
16
|
+
- Record provenance for copied or adapted upstream tests.
|
|
17
|
+
- Keep `skills/claude/SKILL.md` as a symlink to `skills/codex/SKILL.md`.
|
|
18
|
+
|
|
19
|
+
## Command Contract
|
|
20
|
+
|
|
21
|
+
Every command returns a JSON object with this successful shape:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"ok": true,
|
|
26
|
+
"command": "inspect",
|
|
27
|
+
"data": {},
|
|
28
|
+
"warnings": [],
|
|
29
|
+
"artifacts": []
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Every failure returns this shape:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"ok": false,
|
|
38
|
+
"command": "inspect",
|
|
39
|
+
"errorCode": "file_not_found",
|
|
40
|
+
"message": "Workbook file does not exist",
|
|
41
|
+
"details": {},
|
|
42
|
+
"warnings": [],
|
|
43
|
+
"artifacts": []
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Required Verification
|
|
48
|
+
|
|
49
|
+
Before completing a change, run:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
rtk uv run pytest
|
|
53
|
+
rtk uv run ruff check .
|
|
54
|
+
rtk uv run ruff format --check .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Contribution Flow
|
|
58
|
+
|
|
59
|
+
1. Pick one public behavior.
|
|
60
|
+
2. Add or port the failing test first.
|
|
61
|
+
3. Run the focused test and confirm the red state.
|
|
62
|
+
4. Implement the smallest code that passes.
|
|
63
|
+
5. Run the focused tests and relevant suite.
|
|
64
|
+
6. Update examples or skills only after behavior is stable.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zalos
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: zalos-sheetops
|
|
3
|
+
Version: 0.4.2
|
|
4
|
+
Summary: Agent-native Excel and CSV operations toolkit
|
|
5
|
+
Project-URL: Repository, https://github.com/Zalos-io/zalos-sheetops
|
|
6
|
+
Project-URL: Issues, https://github.com/Zalos-io/zalos-sheetops/issues
|
|
7
|
+
Author: Zalos
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Requires-Dist: openpyxl<4,>=3.1.0
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# Zalos SheetOps
|
|
17
|
+
|
|
18
|
+
Agent-native Excel and CSV operations toolkit.
|
|
19
|
+
|
|
20
|
+
The project prioritizes precise, deterministic spreadsheet operations for AI
|
|
21
|
+
agents. Features are added test-first and exposed through machine-readable CLI
|
|
22
|
+
contracts before agents are encouraged to rely on them.
|
|
23
|
+
|
|
24
|
+
## Agent Examples
|
|
25
|
+
|
|
26
|
+
Every command prints one line of compact JSON by default. Pass `--pretty` when
|
|
27
|
+
a human needs to read the output; `--raw-output` remains accepted as a
|
|
28
|
+
deprecated alias for the default.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
sheetops doctor libreoffice
|
|
32
|
+
sheetops inspect --json '{"path":"output.xlsx","engine":"auto","maxFormulaCells":20}'
|
|
33
|
+
sheetops read-table --json '{"path":"output.xlsx","sheet":"Data","headerStrategy":"row","headerRow":1,"maxRows":50}'
|
|
34
|
+
sheetops cells read --json '{"path":"output.xlsx","sheet":"Summary","range":"A1:D20","include":["values","formulas","cachedValues","numberFormats"]}'
|
|
35
|
+
sheetops cells search --json '{"path":"output.xlsx","query":"#4BACC6","fields":["fillColors"],"sheet":"Summary","range":"A1:Z200","limit":100,"offset":0}'
|
|
36
|
+
sheetops hyperlinks assert --json '{"path":"output.xlsx","sheet":"Summary","checks":[{"cell":"B2","target":"https://example.com/customer","display":"Customer portal"}]}'
|
|
37
|
+
sheetops styles assert --json '{"path":"output.xlsx","sheet":"Merchant","checks":[{"cell":"E2","fill":"#D9EAF7"},{"cell":"H2","commentContains":"Method of Payment Code"},{"cell":"G3","fill":"#D9EAF7","formula":true}]}'
|
|
38
|
+
sheetops formulas scan --json '{"path":"output.xlsx","sheet":"Summary","range":"A1:D50","include":["errors"],"failFast":true,"engine":"auto"}'
|
|
39
|
+
sheetops normalize preview --json '{"path":"input.xlsx","sheet":"Data","headerStrategy":"detect","columns":[{"source":"Amount","kind":"amount","name":"amount"}]}'
|
|
40
|
+
sheetops recalc --json '{"path":"output.xlsx","outputDir":"outputs/recalc"}'
|
|
41
|
+
sheetops diff --json '{"left":{"path":"actual.csv"},"right":{"path":"expected.csv"},"keyColumns":["reference"],"compareColumns":["amount"],"amountTolerance":"0.00"}'
|
|
42
|
+
sheetops reconcile --json '{"left":{"path":"bank.csv"},"right":{"path":"processor.csv"},"leftKeyColumns":["reference"],"rightKeyColumns":["reference"],"leftAmountColumn":"amount","rightAmountColumn":"amount","amountTolerance":"0.01"}'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Run `scripts/setup-libreoffice` when `sheetops doctor libreoffice`
|
|
46
|
+
reports that LibreOffice is missing or broken. The script prints the appropriate
|
|
47
|
+
macOS or Linux install command and never runs `sudo` automatically.
|
|
48
|
+
|
|
49
|
+
`inspect` defaults to the XML engine so large workbook metadata checks do not
|
|
50
|
+
materialize every worksheet through OpenPyXL. Keep OpenPyXL read-only usage to
|
|
51
|
+
bounded cell or range commands where the requested area is explicit.
|
|
52
|
+
Inspection reports exact sheet visibility, defined names, bounded merged ranges,
|
|
53
|
+
and chart/image anchors. `cells search` stops at `maxCells` and reports
|
|
54
|
+
`stoppedEarly` rather than silently claiming a complete result.
|
|
55
|
+
|
|
56
|
+
Keep responses token-bounded: `maxRows` on table reads, `maxFormulaCells` on
|
|
57
|
+
inspect (default 20), `maxResults` on scans, and explicit `include` lists on
|
|
58
|
+
cell reads. `read-table` returns `headers` plus positional `rows` arrays and
|
|
59
|
+
stops scanning at `maxRows` under `headerStrategy` `row`, reporting
|
|
60
|
+
`"rowCount": null` with `"truncated": true` when the total is unknown.
|
|
61
|
+
`cells read` omits blank cells and null formulas; compare `returnedCellCount`
|
|
62
|
+
with `cellCount` to see how many cells were blank.
|
|
63
|
+
|
|
64
|
+
## Verification
|
|
65
|
+
|
|
66
|
+
Run these before claiming a change is ready:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
rtk uv run pytest
|
|
70
|
+
rtk uv run ruff check .
|
|
71
|
+
rtk uv run ruff format --check .
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Releases
|
|
75
|
+
|
|
76
|
+
`v0.4.2` is the first public release, with MIT licensing and public package metadata.
|
|
77
|
+
It preserves the `v0.4.1` behavior baseline. It fixes worksheet bounds inspection
|
|
78
|
+
when dimension metadata is missing or invalid, including implicit row and cell
|
|
79
|
+
coordinates. This prevents non-empty worksheets from being reported as `A1`.
|
|
80
|
+
|
|
81
|
+
The `v0.4.0` release added deterministic, bounded
|
|
82
|
+
`cells search` across values, formulas, cached values, number formats, font
|
|
83
|
+
colors, and fill colors, with regex, pagination, hidden-sheet control, and
|
|
84
|
+
explicit scan limits. XML inspection now reports exact sheet states, defined
|
|
85
|
+
names, merged-range metadata, and chart/image anchors while failing closed
|
|
86
|
+
with `invalid_workbook` for malformed drawing relationships. Metadata output
|
|
87
|
+
is independently truncated without hiding total counts.
|
|
88
|
+
|
|
89
|
+
It builds on the `v0.3.1` performance and agent-output release, including the
|
|
90
|
+
packaging guard that keeps `zalos_sheetops.__version__` aligned with the
|
|
91
|
+
distribution version. The CLI dropped typer/click/rich for a zero-dependency
|
|
92
|
+
dispatcher, so cold start halved again and `--help` renders plain text.
|
|
93
|
+
`read-table` and `normalize preview` stop streaming at `maxRows` under
|
|
94
|
+
explicit header rows (about 80x faster on 100k-row workbooks), `validate`
|
|
95
|
+
runs about twice as fast, and `formulas scan` streams through the shared
|
|
96
|
+
expat engine instead of ElementTree. Output is compact JSON by default with
|
|
97
|
+
`--pretty` opt-in, `read-table` rows are positional arrays under `headers`,
|
|
98
|
+
`cells read` omits blank cells and null formulas and reports
|
|
99
|
+
`returnedCellCount`, `styles read` drops redundant row/column fields, and
|
|
100
|
+
`inspect` caps `formulaCells` at 20 by default (`formulaCellsTruncated`
|
|
101
|
+
signals more). The XML engine now expands shared formulas natively using
|
|
102
|
+
openpyxl's translator, so `cells read`, `formulas scan`, and
|
|
103
|
+
`compare labeled-cells` report the real per-cell formula instead of "=" for
|
|
104
|
+
shared-formula followers, and formula scans on shared-formula workbooks no
|
|
105
|
+
longer fall back to the slow openpyxl load. Two precision fixes validated
|
|
106
|
+
against 100MB+ production workbooks: `inspect` tag counting no longer drops
|
|
107
|
+
tags that straddle its internal 1MB scan-chunk boundaries, and `maxResults`
|
|
108
|
+
on `formulas scan` caps returned items across the whole workbook on both
|
|
109
|
+
engines instead of per sheet. The envelope contract
|
|
110
|
+
(`ok`/`command`/`data`/`warnings`/`artifacts`) is unchanged. Consumers upgrading from `v0.2.11` must adapt to
|
|
111
|
+
the new `data` payload shapes for `read-table`, `cells read`, and
|
|
112
|
+
`styles read`, and to the compact default output.
|
|
113
|
+
|
|
114
|
+
It includes the `v0.1.0` `inspect`, `read-table`, `validate`, and
|
|
115
|
+
`formulas scan` baseline, plus fixture-backed `cells read`, scoped formula
|
|
116
|
+
scanning, validation rules, LibreOffice doctor/recalc support, normalization,
|
|
117
|
+
diff, reconciliation, style/comment assertion commands, display overflow
|
|
118
|
+
scanning, italic style assertions, style extraction for bounded cell ranges,
|
|
119
|
+
and a fast XML-backed style assertion path for targeted formula, fill, and
|
|
120
|
+
comment checks. Formula scanning defaults to the faster XML engine, supports
|
|
121
|
+
formula/error category selection, supports fail-fast formula error checks,
|
|
122
|
+
and falls back to `openpyxl` for unsupported workbook features. Hyperlink
|
|
123
|
+
assertion supports cell-targeted XML validation for external or internal
|
|
124
|
+
targets, display text, and tooltips. Workbook inspection defaults to the XML
|
|
125
|
+
engine for full-workbook metadata scans, and CLI help explains command
|
|
126
|
+
intent, JSON payloads, and bounded range guidance.
|
|
127
|
+
|
|
128
|
+
## Install
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
python -m pip install zalos-sheetops==0.4.2
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The public repository is https://github.com/Zalos-io/zalos-sheetops.
|
|
135
|
+
Until the initial PyPI release is available, install from its reviewed release tag.
|
|
136
|
+
The internal repository and its history are not part of this public distribution.
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT. Borrowed test fixtures retain their upstream licenses and attribution in
|
|
141
|
+
`tests/fixtures/manifest.json` and the adjacent upstream license files.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Zalos SheetOps
|
|
2
|
+
|
|
3
|
+
Agent-native Excel and CSV operations toolkit.
|
|
4
|
+
|
|
5
|
+
The project prioritizes precise, deterministic spreadsheet operations for AI
|
|
6
|
+
agents. Features are added test-first and exposed through machine-readable CLI
|
|
7
|
+
contracts before agents are encouraged to rely on them.
|
|
8
|
+
|
|
9
|
+
## Agent Examples
|
|
10
|
+
|
|
11
|
+
Every command prints one line of compact JSON by default. Pass `--pretty` when
|
|
12
|
+
a human needs to read the output; `--raw-output` remains accepted as a
|
|
13
|
+
deprecated alias for the default.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
sheetops doctor libreoffice
|
|
17
|
+
sheetops inspect --json '{"path":"output.xlsx","engine":"auto","maxFormulaCells":20}'
|
|
18
|
+
sheetops read-table --json '{"path":"output.xlsx","sheet":"Data","headerStrategy":"row","headerRow":1,"maxRows":50}'
|
|
19
|
+
sheetops cells read --json '{"path":"output.xlsx","sheet":"Summary","range":"A1:D20","include":["values","formulas","cachedValues","numberFormats"]}'
|
|
20
|
+
sheetops cells search --json '{"path":"output.xlsx","query":"#4BACC6","fields":["fillColors"],"sheet":"Summary","range":"A1:Z200","limit":100,"offset":0}'
|
|
21
|
+
sheetops hyperlinks assert --json '{"path":"output.xlsx","sheet":"Summary","checks":[{"cell":"B2","target":"https://example.com/customer","display":"Customer portal"}]}'
|
|
22
|
+
sheetops styles assert --json '{"path":"output.xlsx","sheet":"Merchant","checks":[{"cell":"E2","fill":"#D9EAF7"},{"cell":"H2","commentContains":"Method of Payment Code"},{"cell":"G3","fill":"#D9EAF7","formula":true}]}'
|
|
23
|
+
sheetops formulas scan --json '{"path":"output.xlsx","sheet":"Summary","range":"A1:D50","include":["errors"],"failFast":true,"engine":"auto"}'
|
|
24
|
+
sheetops normalize preview --json '{"path":"input.xlsx","sheet":"Data","headerStrategy":"detect","columns":[{"source":"Amount","kind":"amount","name":"amount"}]}'
|
|
25
|
+
sheetops recalc --json '{"path":"output.xlsx","outputDir":"outputs/recalc"}'
|
|
26
|
+
sheetops diff --json '{"left":{"path":"actual.csv"},"right":{"path":"expected.csv"},"keyColumns":["reference"],"compareColumns":["amount"],"amountTolerance":"0.00"}'
|
|
27
|
+
sheetops reconcile --json '{"left":{"path":"bank.csv"},"right":{"path":"processor.csv"},"leftKeyColumns":["reference"],"rightKeyColumns":["reference"],"leftAmountColumn":"amount","rightAmountColumn":"amount","amountTolerance":"0.01"}'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Run `scripts/setup-libreoffice` when `sheetops doctor libreoffice`
|
|
31
|
+
reports that LibreOffice is missing or broken. The script prints the appropriate
|
|
32
|
+
macOS or Linux install command and never runs `sudo` automatically.
|
|
33
|
+
|
|
34
|
+
`inspect` defaults to the XML engine so large workbook metadata checks do not
|
|
35
|
+
materialize every worksheet through OpenPyXL. Keep OpenPyXL read-only usage to
|
|
36
|
+
bounded cell or range commands where the requested area is explicit.
|
|
37
|
+
Inspection reports exact sheet visibility, defined names, bounded merged ranges,
|
|
38
|
+
and chart/image anchors. `cells search` stops at `maxCells` and reports
|
|
39
|
+
`stoppedEarly` rather than silently claiming a complete result.
|
|
40
|
+
|
|
41
|
+
Keep responses token-bounded: `maxRows` on table reads, `maxFormulaCells` on
|
|
42
|
+
inspect (default 20), `maxResults` on scans, and explicit `include` lists on
|
|
43
|
+
cell reads. `read-table` returns `headers` plus positional `rows` arrays and
|
|
44
|
+
stops scanning at `maxRows` under `headerStrategy` `row`, reporting
|
|
45
|
+
`"rowCount": null` with `"truncated": true` when the total is unknown.
|
|
46
|
+
`cells read` omits blank cells and null formulas; compare `returnedCellCount`
|
|
47
|
+
with `cellCount` to see how many cells were blank.
|
|
48
|
+
|
|
49
|
+
## Verification
|
|
50
|
+
|
|
51
|
+
Run these before claiming a change is ready:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
rtk uv run pytest
|
|
55
|
+
rtk uv run ruff check .
|
|
56
|
+
rtk uv run ruff format --check .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Releases
|
|
60
|
+
|
|
61
|
+
`v0.4.2` is the first public release, with MIT licensing and public package metadata.
|
|
62
|
+
It preserves the `v0.4.1` behavior baseline. It fixes worksheet bounds inspection
|
|
63
|
+
when dimension metadata is missing or invalid, including implicit row and cell
|
|
64
|
+
coordinates. This prevents non-empty worksheets from being reported as `A1`.
|
|
65
|
+
|
|
66
|
+
The `v0.4.0` release added deterministic, bounded
|
|
67
|
+
`cells search` across values, formulas, cached values, number formats, font
|
|
68
|
+
colors, and fill colors, with regex, pagination, hidden-sheet control, and
|
|
69
|
+
explicit scan limits. XML inspection now reports exact sheet states, defined
|
|
70
|
+
names, merged-range metadata, and chart/image anchors while failing closed
|
|
71
|
+
with `invalid_workbook` for malformed drawing relationships. Metadata output
|
|
72
|
+
is independently truncated without hiding total counts.
|
|
73
|
+
|
|
74
|
+
It builds on the `v0.3.1` performance and agent-output release, including the
|
|
75
|
+
packaging guard that keeps `zalos_sheetops.__version__` aligned with the
|
|
76
|
+
distribution version. The CLI dropped typer/click/rich for a zero-dependency
|
|
77
|
+
dispatcher, so cold start halved again and `--help` renders plain text.
|
|
78
|
+
`read-table` and `normalize preview` stop streaming at `maxRows` under
|
|
79
|
+
explicit header rows (about 80x faster on 100k-row workbooks), `validate`
|
|
80
|
+
runs about twice as fast, and `formulas scan` streams through the shared
|
|
81
|
+
expat engine instead of ElementTree. Output is compact JSON by default with
|
|
82
|
+
`--pretty` opt-in, `read-table` rows are positional arrays under `headers`,
|
|
83
|
+
`cells read` omits blank cells and null formulas and reports
|
|
84
|
+
`returnedCellCount`, `styles read` drops redundant row/column fields, and
|
|
85
|
+
`inspect` caps `formulaCells` at 20 by default (`formulaCellsTruncated`
|
|
86
|
+
signals more). The XML engine now expands shared formulas natively using
|
|
87
|
+
openpyxl's translator, so `cells read`, `formulas scan`, and
|
|
88
|
+
`compare labeled-cells` report the real per-cell formula instead of "=" for
|
|
89
|
+
shared-formula followers, and formula scans on shared-formula workbooks no
|
|
90
|
+
longer fall back to the slow openpyxl load. Two precision fixes validated
|
|
91
|
+
against 100MB+ production workbooks: `inspect` tag counting no longer drops
|
|
92
|
+
tags that straddle its internal 1MB scan-chunk boundaries, and `maxResults`
|
|
93
|
+
on `formulas scan` caps returned items across the whole workbook on both
|
|
94
|
+
engines instead of per sheet. The envelope contract
|
|
95
|
+
(`ok`/`command`/`data`/`warnings`/`artifacts`) is unchanged. Consumers upgrading from `v0.2.11` must adapt to
|
|
96
|
+
the new `data` payload shapes for `read-table`, `cells read`, and
|
|
97
|
+
`styles read`, and to the compact default output.
|
|
98
|
+
|
|
99
|
+
It includes the `v0.1.0` `inspect`, `read-table`, `validate`, and
|
|
100
|
+
`formulas scan` baseline, plus fixture-backed `cells read`, scoped formula
|
|
101
|
+
scanning, validation rules, LibreOffice doctor/recalc support, normalization,
|
|
102
|
+
diff, reconciliation, style/comment assertion commands, display overflow
|
|
103
|
+
scanning, italic style assertions, style extraction for bounded cell ranges,
|
|
104
|
+
and a fast XML-backed style assertion path for targeted formula, fill, and
|
|
105
|
+
comment checks. Formula scanning defaults to the faster XML engine, supports
|
|
106
|
+
formula/error category selection, supports fail-fast formula error checks,
|
|
107
|
+
and falls back to `openpyxl` for unsupported workbook features. Hyperlink
|
|
108
|
+
assertion supports cell-targeted XML validation for external or internal
|
|
109
|
+
targets, display text, and tooltips. Workbook inspection defaults to the XML
|
|
110
|
+
engine for full-workbook metadata scans, and CLI help explains command
|
|
111
|
+
intent, JSON payloads, and bounded range guidance.
|
|
112
|
+
|
|
113
|
+
## Install
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
python -m pip install zalos-sheetops==0.4.2
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The public repository is https://github.com/Zalos-io/zalos-sheetops.
|
|
120
|
+
Until the initial PyPI release is available, install from its reviewed release tag.
|
|
121
|
+
The internal repository and its history are not part of this public distribution.
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
MIT. Borrowed test fixtures retain their upstream licenses and attribution in
|
|
126
|
+
`tests/fixtures/manifest.json` and the adjacent upstream license files.
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# SheetOps Architecture And Reference Repositories
|
|
2
|
+
|
|
3
|
+
This document is the orientation file for future AI agents contributing to
|
|
4
|
+
`zalos-sheetops`. It explains the package architecture, the trust model, and
|
|
5
|
+
the external repositories we studied or borrowed fixtures from.
|
|
6
|
+
|
|
7
|
+
## Product Goal
|
|
8
|
+
|
|
9
|
+
`zalos-sheetops` is an agent-native Excel and CSV toolkit for Codex, Claude
|
|
10
|
+
Code, and financial-agent workflows. Its job is to make common spreadsheet
|
|
11
|
+
operations precise, deterministic, and safe enough that agents can call a
|
|
12
|
+
tested command instead of rewriting spreadsheet logic inside every financial
|
|
13
|
+
agent.
|
|
14
|
+
|
|
15
|
+
The package favors a small set of trusted operations over a large set of
|
|
16
|
+
loosely-tested helpers.
|
|
17
|
+
|
|
18
|
+
## Architecture
|
|
19
|
+
|
|
20
|
+
The public surface is a JSON-first CLI plus small Python library modules behind
|
|
21
|
+
each command.
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
src/zalos_sheetops/
|
|
25
|
+
cli.py # JSON CLI dispatcher
|
|
26
|
+
command_registry.py # machine-readable command manifest
|
|
27
|
+
contracts.py # success/error response helpers
|
|
28
|
+
errors.py # stable SheetOpsError
|
|
29
|
+
paths.py # path hardening and local file validation
|
|
30
|
+
|
|
31
|
+
io/
|
|
32
|
+
inspect.py # workbook/sheet/cell metadata
|
|
33
|
+
search_cells.py # bounded, paginated value/formula/style search
|
|
34
|
+
headers.py # header detection and canonicalization
|
|
35
|
+
read_table.py # XLSX table extraction
|
|
36
|
+
read_csv_table.py # planned CSV table extraction
|
|
37
|
+
|
|
38
|
+
validation/
|
|
39
|
+
workbook.py # required sheets/columns and uniqueness checks
|
|
40
|
+
|
|
41
|
+
normalize/
|
|
42
|
+
text.py # header/text canonicalization
|
|
43
|
+
amounts.py # planned amount normalization
|
|
44
|
+
dates.py # planned date normalization
|
|
45
|
+
preview.py # planned normalize-preview command logic
|
|
46
|
+
|
|
47
|
+
formulas/
|
|
48
|
+
scan.py # formula and formula-error discovery
|
|
49
|
+
|
|
50
|
+
recalc/
|
|
51
|
+
libreoffice.py # planned LibreOffice recalculation wrapper
|
|
52
|
+
|
|
53
|
+
diff/
|
|
54
|
+
tabular.py # planned table diff helpers
|
|
55
|
+
|
|
56
|
+
reconcile/
|
|
57
|
+
exact.py # planned exact reconciliation helpers
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Command Contract
|
|
61
|
+
|
|
62
|
+
Every command returns structured JSON. Agents should parse these fields and
|
|
63
|
+
avoid parsing human prose.
|
|
64
|
+
|
|
65
|
+
Success:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"ok": true,
|
|
70
|
+
"command": "inspect",
|
|
71
|
+
"data": {},
|
|
72
|
+
"warnings": [],
|
|
73
|
+
"artifacts": []
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Failure:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"ok": false,
|
|
82
|
+
"command": "inspect",
|
|
83
|
+
"errorCode": "file_not_found",
|
|
84
|
+
"message": "Workbook file does not exist",
|
|
85
|
+
"details": {},
|
|
86
|
+
"warnings": [],
|
|
87
|
+
"artifacts": []
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Trust Model
|
|
92
|
+
|
|
93
|
+
- Public behavior starts with a failing test.
|
|
94
|
+
- Tests must verify exact JSON shapes for CLI behavior.
|
|
95
|
+
- Real workbook behavior should use fixture-backed tests where possible.
|
|
96
|
+
- Fixture provenance is mandatory for borrowed files.
|
|
97
|
+
- Commands fail closed when inputs are ambiguous.
|
|
98
|
+
- Source files are not mutated by default.
|
|
99
|
+
- Recalculation and generated outputs must go to explicit output paths.
|
|
100
|
+
|
|
101
|
+
## Fixture Strategy
|
|
102
|
+
|
|
103
|
+
Fixtures live under `tests/fixtures/`.
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
tests/fixtures/
|
|
107
|
+
README.md
|
|
108
|
+
manifest.json
|
|
109
|
+
upstream/
|
|
110
|
+
calamine/
|
|
111
|
+
fastexcel/
|
|
112
|
+
openpyxl/
|
|
113
|
+
xlsx2csv/
|
|
114
|
+
xlsxwriter/
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Every upstream fixture must be registered in
|
|
118
|
+
`tests/fixtures/manifest.json` with:
|
|
119
|
+
|
|
120
|
+
- `fixtureId`
|
|
121
|
+
- `sourceRepo`
|
|
122
|
+
- `sourcePath`
|
|
123
|
+
- `license`
|
|
124
|
+
- `destination`
|
|
125
|
+
- `sha256`
|
|
126
|
+
- `behavior`
|
|
127
|
+
|
|
128
|
+
The manifest hash-locks fixture files so agents cannot unknowingly change test
|
|
129
|
+
ground truth.
|
|
130
|
+
|
|
131
|
+
## Reference Repositories
|
|
132
|
+
|
|
133
|
+
These repositories were used as design or fixture references.
|
|
134
|
+
|
|
135
|
+
### Spreadsheet Agent Skill
|
|
136
|
+
|
|
137
|
+
| Repo | Used For |
|
|
138
|
+
| --- | --- |
|
|
139
|
+
| `anthropics/skills` | `xlsx` skill conventions: formula-first workbooks, LibreOffice recalc, formula-error scans, color conventions, and agent-facing spreadsheet workflows |
|
|
140
|
+
| `dust-tt/dust@dc59bd33` (`front/lib/api/sandbox/image/profile/soffice/xlsx_inspect.py`) | MIT-licensed design reference for drawing-aware inspection, defined names, displayed color resolution, and paginated workbook search. No upstream implementation or tests were copied; SheetOps behavior was specified and tested independently. |
|
|
141
|
+
|
|
142
|
+
### Core Workbook IO And Writing
|
|
143
|
+
|
|
144
|
+
| Repo | License | Used For |
|
|
145
|
+
| --- | --- | --- |
|
|
146
|
+
| `openpyxl` | MIT | Existing workbook inspection, formula text vs cached values, hidden sheets, hyperlinks, comments, defined names, formula token/translation behavior, XLSX fixtures |
|
|
147
|
+
| `XlsxWriter` | BSD-2-Clause | Generated workbook guardrails, formula writing, tables, data validation, conditional formatting, overlap checks, comparison XLSX fixtures |
|
|
148
|
+
| `fastexcel` | MIT | Fast Excel ingestion patterns, `header_row`, `skip_rows`, whitespace, duplicate columns, sheet visibility, table-offset fixtures |
|
|
149
|
+
| `calamine` | MIT | Cross-format spreadsheet parsing behavior, formula edge cases, shared formulas, `.xls`/`.xlsb`/`.ods` future support, fixtures |
|
|
150
|
+
|
|
151
|
+
### Data Processing
|
|
152
|
+
|
|
153
|
+
| Repo | Used For |
|
|
154
|
+
| --- | --- |
|
|
155
|
+
| `polars` | DataFrame transform patterns: `select`, `with_columns`, `filter`, `group_by`, `join`, `concat`, lazy scans |
|
|
156
|
+
| `pandas` | Excel/CSV IO option reference: sheet selection, `header`, `dtype`, `parse_dates`, `thousands`, `decimal`, `skipfooter` |
|
|
157
|
+
| `numpy` | Numeric behavior reference only; not a primary SheetOps dependency |
|
|
158
|
+
|
|
159
|
+
### Validation And Data Contracts
|
|
160
|
+
|
|
161
|
+
| Repo | Used For |
|
|
162
|
+
| --- | --- |
|
|
163
|
+
| `pandera` | Schema/check design: required columns, strict schemas, uniqueness, nullable/coerce behavior, dataframe-level checks |
|
|
164
|
+
| `frictionless-py` | File/table diagnostics: dialect, header rows, missing values, checklist-style validation |
|
|
165
|
+
| `great_expectations` | Expectation-style validation concepts and reporting vocabulary |
|
|
166
|
+
|
|
167
|
+
### Matching And Reconciliation
|
|
168
|
+
|
|
169
|
+
| Repo | Used For |
|
|
170
|
+
| --- | --- |
|
|
171
|
+
| `RapidFuzz` | Future fuzzy matching, string similarity thresholds, scorer behavior |
|
|
172
|
+
|
|
173
|
+
### CSV, Diff, And Conversion
|
|
174
|
+
|
|
175
|
+
| Repo | License | Used For |
|
|
176
|
+
| --- | --- | --- |
|
|
177
|
+
| `xlsx2csv` | MIT | XLSX-to-CSV fixtures and expected CSV baselines for datetimes, UTF-8, empty rows, hyperlinks, delimiters |
|
|
178
|
+
| `csvkit` | MIT | CSV dialect and cleanup edge cases: BOM, Latin-1, short/long rows, no-header files, newline behavior |
|
|
179
|
+
| `csv-diff` | Apache-2.0 | Keyed row diff shape: added rows, removed rows, changed rows |
|
|
180
|
+
| `daff` | MIT | Table diff concepts, row/column alignment, patch-style comparison behavior |
|
|
181
|
+
|
|
182
|
+
### Formula Evaluation And Recalculation
|
|
183
|
+
|
|
184
|
+
| Repo | Used For |
|
|
185
|
+
| --- | --- |
|
|
186
|
+
| `xlcalculator` | Offline formula-evaluation reference and limitations |
|
|
187
|
+
| `formulas` | Formula parser/evaluator reference, supported function landscape, compare-method ideas |
|
|
188
|
+
| LibreOffice | Primary future recalculation path because it recalculates real XLSX workbooks instead of approximating Excel behavior |
|
|
189
|
+
|
|
190
|
+
## Borrowed Fixture Sources
|
|
191
|
+
|
|
192
|
+
The current fixture manifest borrows files from:
|
|
193
|
+
|
|
194
|
+
- `fastexcel`
|
|
195
|
+
- `calamine`
|
|
196
|
+
- `openpyxl`
|
|
197
|
+
- `xlsx2csv`
|
|
198
|
+
- `XlsxWriter`
|
|
199
|
+
|
|
200
|
+
See `tests/fixtures/manifest.json` for exact source paths, destination paths,
|
|
201
|
+
licenses, SHA256 hashes, and the behavior each fixture protects.
|
|
202
|
+
|
|
203
|
+
## How To Add A New Reference Or Fixture
|
|
204
|
+
|
|
205
|
+
1. Prefer a small synthetic fixture if it proves the behavior.
|
|
206
|
+
2. Borrow an upstream fixture only when real workbook structure matters.
|
|
207
|
+
3. Copy the file into `tests/fixtures/upstream/<repo>/`.
|
|
208
|
+
4. Record source repo, source path, license, destination, SHA256, and protected
|
|
209
|
+
behavior in `tests/fixtures/manifest.json`.
|
|
210
|
+
5. Add or update a test that fails before the implementation change.
|
|
211
|
+
6. Run:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
rtk uv run pytest
|
|
215
|
+
rtk uv run ruff check .
|
|
216
|
+
rtk uv run ruff format --check .
|
|
217
|
+
```
|
|
218
|
+
|