python-calamine-reducto 0.7.6__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.
Files changed (60) hide show
  1. python_calamine_reducto-0.7.6/.github/workflows/CI.yml +67 -0
  2. python_calamine_reducto-0.7.6/.gitignore +141 -0
  3. python_calamine_reducto-0.7.6/.pre-commit-config.yaml +64 -0
  4. python_calamine_reducto-0.7.6/.python-version +1 -0
  5. python_calamine_reducto-0.7.6/CLAUDE.md +131 -0
  6. python_calamine_reducto-0.7.6/Cargo.lock +1091 -0
  7. python_calamine_reducto-0.7.6/Cargo.toml +23 -0
  8. python_calamine_reducto-0.7.6/LICENSE +21 -0
  9. python_calamine_reducto-0.7.6/PKG-INFO +15 -0
  10. python_calamine_reducto-0.7.6/README.md +158 -0
  11. python_calamine_reducto-0.7.6/build.rs +3 -0
  12. python_calamine_reducto-0.7.6/pyproject.toml +52 -0
  13. python_calamine_reducto-0.7.6/python/python_calamine/__init__.py +43 -0
  14. python_calamine_reducto-0.7.6/python/python_calamine/_python_calamine.pyi +316 -0
  15. python_calamine_reducto-0.7.6/python/python_calamine/py.typed +0 -0
  16. python_calamine_reducto-0.7.6/renovate.json +6 -0
  17. python_calamine_reducto-0.7.6/src/lib.rs +44 -0
  18. python_calamine_reducto-0.7.6/src/types/cell.rs +133 -0
  19. python_calamine_reducto-0.7.6/src/types/errors.rs +78 -0
  20. python_calamine_reducto-0.7.6/src/types/grid.rs +1745 -0
  21. python_calamine_reducto-0.7.6/src/types/mod.rs +15 -0
  22. python_calamine_reducto-0.7.6/src/types/sheet.rs +282 -0
  23. python_calamine_reducto-0.7.6/src/types/table.rs +71 -0
  24. python_calamine_reducto-0.7.6/src/types/workbook.rs +1097 -0
  25. python_calamine_reducto-0.7.6/tests/__init__.py +0 -0
  26. python_calamine_reducto-0.7.6/tests/conftest.py +73 -0
  27. python_calamine_reducto-0.7.6/tests/create_empty_merge_fixture.py +34 -0
  28. python_calamine_reducto-0.7.6/tests/create_richtext_fixture.py +126 -0
  29. python_calamine_reducto-0.7.6/tests/create_test_fixture.py +90 -0
  30. python_calamine_reducto-0.7.6/tests/data/any_sheets.ods +0 -0
  31. python_calamine_reducto-0.7.6/tests/data/any_sheets.xls +0 -0
  32. python_calamine_reducto-0.7.6/tests/data/any_sheets.xlsb +0 -0
  33. python_calamine_reducto-0.7.6/tests/data/any_sheets.xlsx +0 -0
  34. python_calamine_reducto-0.7.6/tests/data/base.ods +0 -0
  35. python_calamine_reducto-0.7.6/tests/data/base.xls +0 -0
  36. python_calamine_reducto-0.7.6/tests/data/base.xlsb +0 -0
  37. python_calamine_reducto-0.7.6/tests/data/base.xlsx +0 -0
  38. python_calamine_reducto-0.7.6/tests/data/dropdown_test.xlsx +0 -0
  39. python_calamine_reducto-0.7.6/tests/data/empty_file.ods +0 -0
  40. python_calamine_reducto-0.7.6/tests/data/empty_file.xlsb +0 -0
  41. python_calamine_reducto-0.7.6/tests/data/empty_file.xlsx +0 -0
  42. python_calamine_reducto-0.7.6/tests/data/empty_merge_test.xlsx +0 -0
  43. python_calamine_reducto-0.7.6/tests/data/formula_test.xlsx +0 -0
  44. python_calamine_reducto-0.7.6/tests/data/grid_test.xlsx +0 -0
  45. python_calamine_reducto-0.7.6/tests/data/image_test.xlsx +0 -0
  46. python_calamine_reducto-0.7.6/tests/data/issue139.xlsx +0 -0
  47. python_calamine_reducto-0.7.6/tests/data/multi_image_test.xlsx +0 -0
  48. python_calamine_reducto-0.7.6/tests/data/password.ods +0 -0
  49. python_calamine_reducto-0.7.6/tests/data/password.xls +0 -0
  50. python_calamine_reducto-0.7.6/tests/data/password.xlsb +0 -0
  51. python_calamine_reducto-0.7.6/tests/data/password.xlsx +0 -0
  52. python_calamine_reducto-0.7.6/tests/data/richtext_test.xlsx +0 -0
  53. python_calamine_reducto-0.7.6/tests/data/table-multiple.xlsx +0 -0
  54. python_calamine_reducto-0.7.6/tests/test_base.py +384 -0
  55. python_calamine_reducto-0.7.6/tests/test_grid.py +1093 -0
  56. python_calamine_reducto-0.7.6/tests/test_images.py +128 -0
  57. python_calamine_reducto-0.7.6/tests/test_pandas.py +112 -0
  58. python_calamine_reducto-0.7.6/tests/test_sheet_type.py +120 -0
  59. python_calamine_reducto-0.7.6/tests/test_tables.py +73 -0
  60. python_calamine_reducto-0.7.6/uv.lock +1065 -0
@@ -0,0 +1,67 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request: {}
8
+
9
+ jobs:
10
+ test:
11
+ name: test ${{ matrix.python-version }}
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version:
16
+ - "3.11"
17
+ - "3.12"
18
+ - "3.13"
19
+
20
+ runs-on: ubuntu-latest
21
+
22
+ env:
23
+ PYTHON: ${{ matrix.python-version }}
24
+
25
+ steps:
26
+ - uses: actions/checkout@v6
27
+
28
+ - name: configure git for private deps
29
+ run: git config --global url."https://x-access-token:${{ secrets.GH_PAT }}@github.com/".insteadOf "https://github.com/"
30
+
31
+ - name: install rust stable
32
+ uses: dtolnay/rust-toolchain@master
33
+ with:
34
+ toolchain: stable
35
+
36
+ - id: cache-rust
37
+ name: cache rust
38
+ uses: Swatinem/rust-cache@v2
39
+ with:
40
+ key: v3
41
+
42
+ - name: set up python
43
+ uses: actions/setup-python@v6
44
+ with:
45
+ python-version: ${{ matrix.python-version }}
46
+
47
+ - run: pip install pytest numpy
48
+
49
+ - run: pip install -e .
50
+ env:
51
+ RUST_BACKTRACE: 1
52
+ CARGO_NET_GIT_FETCH_WITH_CLI: "true"
53
+
54
+ - run: pytest
55
+
56
+ # https://github.com/marketplace/actions/alls-green#why used for branch protection checks
57
+ check:
58
+ if: always()
59
+ needs: [test]
60
+ runs-on: ubuntu-latest
61
+ steps:
62
+ - name: Decide whether the needed jobs succeeded or failed
63
+ uses: re-actors/alls-green@release/v1
64
+ with:
65
+ jobs: ${{ toJSON(needs) }}
66
+
67
+
@@ -0,0 +1,141 @@
1
+ # Generated by Cargo
2
+ # will have compiled files and executables
3
+ debug/
4
+ target/
5
+
6
+ # These are backup files generated by rustfmt
7
+ **/*.rs.bk
8
+
9
+ # Initial .gitignore from GitHub for Python project
10
+ # Byte-compiled / optimized / DLL files
11
+ __pycache__/
12
+ *.py[cod]
13
+ *$py.class
14
+
15
+ # C extensions
16
+ *.so
17
+
18
+ # Distribution / packaging
19
+ .Python
20
+ build/
21
+ develop-eggs/
22
+ dist/
23
+ downloads/
24
+ eggs/
25
+ .eggs/
26
+ lib/
27
+ lib64/
28
+ parts/
29
+ sdist/
30
+ var/
31
+ wheels/
32
+ pip-wheel-metadata/
33
+ share/python-wheels/
34
+ *.egg-info/
35
+ .installed.cfg
36
+ *.egg
37
+ MANIFEST
38
+
39
+ # PyInstaller
40
+ # Usually these files are written by a python script from a template
41
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
42
+ *.manifest
43
+ *.spec
44
+
45
+ # Installer logs
46
+ pip-log.txt
47
+ pip-delete-this-directory.txt
48
+
49
+ # Unit test / coverage reports
50
+ htmlcov/
51
+ .tox/
52
+ .nox/
53
+ .coverage
54
+ .coverage.*
55
+ .cache
56
+ nosetests.xml
57
+ coverage.xml
58
+ *.cover
59
+ *.py,cover
60
+ .hypothesis/
61
+ .pytest_cache/
62
+
63
+ # Translations
64
+ *.mo
65
+ *.pot
66
+
67
+ # Django stuff:
68
+ *.log
69
+ local_settings.py
70
+ db.sqlite3
71
+ db.sqlite3-journal
72
+
73
+ # Flask stuff:
74
+ instance/
75
+ .webassets-cache
76
+
77
+ # Scrapy stuff:
78
+ .scrapy
79
+
80
+ # Sphinx documentation
81
+ docs/_build/
82
+
83
+ # PyBuilder
84
+ target/
85
+
86
+ # Jupyter Notebook
87
+ .ipynb_checkpoints
88
+
89
+ # IPython
90
+ profile_default/
91
+ ipython_config.py
92
+
93
+ # pyenv
94
+ .python-version
95
+
96
+ # pipenv
97
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
98
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
99
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
100
+ # install all needed dependencies.
101
+ #Pipfile.lock
102
+
103
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
104
+ __pypackages__/
105
+
106
+ # Celery stuff
107
+ celerybeat-schedule
108
+ celerybeat.pid
109
+
110
+ # SageMath parsed files
111
+ *.sage.py
112
+
113
+ # Environments
114
+ .env
115
+ .venv
116
+ env/
117
+ venv/
118
+ ENV/
119
+ env.bak/
120
+ venv.bak/
121
+
122
+ # Spyder project settings
123
+ .spyderproject
124
+ .spyproject
125
+
126
+ # Rope project settings
127
+ .ropeproject
128
+
129
+ # mkdocs documentation
130
+ /site
131
+
132
+ # mypy
133
+ .mypy_cache/
134
+ .dmypy.json
135
+ dmypy.json
136
+
137
+ # Pyre type checker
138
+ .pyre/
139
+
140
+ # IDE stuff
141
+ .vscode
@@ -0,0 +1,64 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.5.0
4
+ hooks:
5
+ - id: check-added-large-files
6
+ - id: check-toml
7
+ - id: check-yaml
8
+ args:
9
+ - --unsafe
10
+ - id: end-of-file-fixer
11
+ - id: trailing-whitespace
12
+ - repo: https://github.com/asottile/pyupgrade
13
+ rev: v3.15.0
14
+ hooks:
15
+ - id: pyupgrade
16
+ args:
17
+ - --py3-plus
18
+ - --keep-runtime-typing
19
+ - repo: https://github.com/charliermarsh/ruff-pre-commit
20
+ rev: v0.2.1
21
+ hooks:
22
+ - id: ruff
23
+ args:
24
+ - --fix
25
+ - repo: https://github.com/pycqa/isort
26
+ rev: 5.13.2
27
+ hooks:
28
+ - id: isort
29
+ name: isort (python)
30
+ - id: isort
31
+ name: isort (pyi)
32
+ types: [pyi]
33
+ - repo: https://github.com/psf/black
34
+ rev: 24.1.1
35
+ hooks:
36
+ - id: black
37
+ - repo: local
38
+ hooks:
39
+ - id: mypy
40
+ name: mypy
41
+ entry: mypy
42
+ language: python
43
+ pass_filenames: false
44
+ - id: mypy-stubtest
45
+ name: mypy-stubtest
46
+ entry: stubtest
47
+ args:
48
+ - python_calamine
49
+ language: python
50
+ pass_filenames: false
51
+ - repo: local
52
+ hooks:
53
+ - id: rust-linting
54
+ name: Rust linting
55
+ entry: cargo fmt --all -- --config group_imports=StdExternalCrate,imports_granularity=Module
56
+ pass_filenames: true
57
+ types: [rust]
58
+ language: system
59
+ - id: rust-clippy
60
+ name: Rust clippy
61
+ entry: cargo clippy -- -D warnings -A incomplete_features -W clippy::dbg_macro -W clippy::print_stdout
62
+ pass_filenames: false
63
+ types: [rust]
64
+ language: system
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,131 @@
1
+ # Reducto python-calamine Fork
2
+
3
+ Private fork of [dimastbk/python-calamine](https://github.com/dimastbk/python-calamine) — PyO3 bindings for the calamine Rust spreadsheet reader.
4
+
5
+ ## What This Repo Is
6
+
7
+ Python bindings for calamine, extended with Reducto's `CellGrid` type and workbook style/layout/bounds APIs. Used by `api4/src/sheets/` as a 40x faster replacement for openpyxl.
8
+
9
+ **Dependency chain:** `api4` → `python-calamine-reducto` (PyPI) → `reductoai/calamine` + `reductoai/ssfmt` (Rust crates, compiled into the wheel)
10
+
11
+ ## Building
12
+
13
+ ```bash
14
+ # Create venv and install
15
+ python3 -m venv .venv && source .venv/bin/activate
16
+ maturin develop # debug build (~4s incremental)
17
+ maturin develop --release # release build (~30s clean)
18
+
19
+ # Or build into api4's venv directly:
20
+ source /path/to/api4/.venv/bin/activate
21
+ maturin develop --release
22
+ ```
23
+
24
+ Requires Rust toolchain (`rustup`). The Cargo.toml pulls `reductoai/calamine` and `reductoai/ssfmt` from git, which are private — you need git auth configured:
25
+ ```bash
26
+ git config --global url."https://x-access-token:YOUR_PAT@github.com/".insteadOf "https://github.com/"
27
+ # OR just have SSH access to reductoai org
28
+ ```
29
+
30
+ ## Testing
31
+
32
+ ```bash
33
+ pip install pytest numpy
34
+ pytest # all tests
35
+ pytest tests/test_grid.py # CellGrid tests only
36
+ pytest tests/test_base.py # upstream tests only
37
+ ```
38
+
39
+ The test fixture `tests/data/grid_test.xlsx` is generated by `tests/create_test_fixture.py` (requires openpyxl). Regenerate if you change test expectations:
40
+ ```bash
41
+ pip install openpyxl
42
+ python tests/create_test_fixture.py
43
+ ```
44
+
45
+ ## Publishing to PyPI
46
+
47
+ **Package name convention:** Reducto forks are published as `{package}-reducto` on PyPI. This package is `python-calamine-reducto`. The Python import stays `python_calamine`.
48
+
49
+ **Steps to publish a new version:**
50
+
51
+ 1. Update version in `Cargo.toml` (e.g., `version = "0.7.1"`)
52
+ 2. Commit, merge to `main`, and tag:
53
+ ```bash
54
+ git tag v0.7.1
55
+ git push origin v0.7.1
56
+ ```
57
+ 3. Build wheels for each target platform:
58
+ ```bash
59
+ # macOS ARM (native):
60
+ maturin build --release --interpreter 3.11 3.12 3.13
61
+
62
+ # manylinux x86_64 (from macOS, via Docker):
63
+ docker run --rm --platform linux/amd64 \
64
+ --entrypoint /bin/bash \
65
+ -v $(pwd):/io \
66
+ -v $HOME/.ssh:/root/.ssh:ro \
67
+ -e CARGO_NET_GIT_FETCH_WITH_CLI=true \
68
+ -e GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no" \
69
+ ghcr.io/pyo3/maturin -c '
70
+ git config --global url."git@github.com:".insteadOf "https://github.com/"
71
+ maturin build --release --interpreter 3.11 3.12 3.13
72
+ '
73
+ ```
74
+ Wheels go into `target/wheels/`.
75
+
76
+ **Note:** The Docker command mounts your SSH keys for private repo access. Ensure Docker Desktop is running and you have SSH access to `reductoai` org repos.
77
+
78
+ 4. Upload to PyPI:
79
+ ```bash
80
+ pip install twine
81
+ twine upload target/wheels/*
82
+ ```
83
+ Uses token from `~/.pypirc`. If not configured:
84
+ ```ini
85
+ # ~/.pypirc
86
+ [pypi]
87
+ username = __token__
88
+ password = pypi-...
89
+ ```
90
+
91
+ 5. Update api4's `pyproject.toml`:
92
+ ```
93
+ "python-calamine-reducto==0.7.1"
94
+ ```
95
+ Then run `uv lock`.
96
+
97
+ **Note:** Because this package has private git dependencies (`reductoai/calamine`, `reductoai/ssfmt`), you need git auth configured when building. The `GH_PAT` or SSH access must be available during `maturin build`.
98
+
99
+ ## Key Files
100
+
101
+ | Path | What |
102
+ |------|------|
103
+ | `src/types/grid.rs` | CellGrid, CellProxy, CellGridView — the core Reducto addition (~1500 lines) |
104
+ | `src/types/workbook.rs` | get_sheet_grid, get_sheet_styles, get_sheet_layout, get_sheet_bounds |
105
+ | `src/types/mod.rs` | Module exports |
106
+ | `src/lib.rs` | PyO3 module registration |
107
+ | `python/python_calamine/__init__.py` | Python re-exports |
108
+ | `Cargo.toml` | Points calamine + ssfmt deps to reductoai forks |
109
+ | `tests/test_grid.py` | 86 tests for all CellGrid APIs |
110
+
111
+ ## Architecture
112
+
113
+ ```
114
+ Python code
115
+ → python_calamine (PyO3 module)
116
+ → CellGrid (src/types/grid.rs) — 2D grid with per-cell value/style/formatting
117
+ → CalamineWorkbook (src/types/workbook.rs) — xlsx/xls/ods reader
118
+ → calamine (Rust crate, from reductoai/calamine) — parsing + styles
119
+ → ssfmt (Rust crate, from reductoai/ssfmt) — ECMA-376 number formatting
120
+ ```
121
+
122
+ **CellGrid fields per cell:** value, formatted_value, font_bold, font_size, number_format, cell_textcolor, cell_highlight, cell_formula, header, is_merged, merge_parent, coord
123
+
124
+ ## Making Changes
125
+
126
+ 1. Branch from `main`
127
+ 2. Edit Rust code, rebuild with `maturin develop`
128
+ 3. Run `pytest` to verify
129
+ 4. Push, open PR against `main`
130
+
131
+ If you changed something in `reductoai/calamine` or `reductoai/ssfmt`, merge those PRs first — this repo's `Cargo.toml` tracks `branch = "main"` for both.