python-calamine 0.4.0__tar.gz → 0.5.1__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.
- {python_calamine-0.4.0 → python_calamine-0.5.1}/.github/workflows/CI.yml +26 -39
- {python_calamine-0.4.0 → python_calamine-0.5.1}/.pre-commit-config.yaml +0 -2
- {python_calamine-0.4.0 → python_calamine-0.5.1}/Cargo.lock +39 -64
- python_calamine-0.5.1/Cargo.toml +22 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/PKG-INFO +6 -26
- {python_calamine-0.4.0 → python_calamine-0.5.1}/README.md +0 -13
- {python_calamine-0.4.0 → python_calamine-0.5.1}/pyproject.toml +9 -9
- {python_calamine-0.4.0 → python_calamine-0.5.1}/src/lib.rs +1 -1
- {python_calamine-0.4.0 → python_calamine-0.5.1}/src/types/cell.rs +32 -4
- {python_calamine-0.4.0 → python_calamine-0.5.1}/src/types/sheet.rs +9 -6
- {python_calamine-0.4.0 → python_calamine-0.5.1}/src/types/workbook.rs +16 -16
- python_calamine-0.5.1/tests/data/issue139.xlsx +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/test_base.py +7 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/test_pandas.py +0 -13
- python_calamine-0.4.0/Cargo.toml +0 -27
- python_calamine-0.4.0/python/python_calamine/pandas.py +0 -136
- {python_calamine-0.4.0 → python_calamine-0.5.1}/.gitignore +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/LICENSE +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/build.rs +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/python/python_calamine/__init__.py +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/python/python_calamine/_python_calamine.pyi +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/python/python_calamine/py.typed +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/renovate.json +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/src/types/errors.rs +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/src/types/mod.rs +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/src/utils.rs +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/__init__.py +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/conftest.py +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/any_sheets.ods +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/any_sheets.xls +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/any_sheets.xlsb +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/any_sheets.xlsx +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/base.ods +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/base.xls +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/base.xlsb +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/base.xlsx +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/empty_file.ods +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/empty_file.xlsb +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/empty_file.xlsx +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/password.ods +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/password.xls +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/password.xlsb +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/data/password.xlsx +0 -0
- {python_calamine-0.4.0 → python_calamine-0.5.1}/tests/test_sheet_type.py +0 -0
|
@@ -13,33 +13,29 @@ on:
|
|
|
13
13
|
|
|
14
14
|
jobs:
|
|
15
15
|
test:
|
|
16
|
-
name: test ${{ matrix.python-version }} pandas ${{ matrix.pandas-version }}
|
|
16
|
+
name: test ${{ matrix.python-version }} pandas ${{ matrix.pandas-version }}
|
|
17
17
|
strategy:
|
|
18
18
|
fail-fast: false
|
|
19
19
|
matrix:
|
|
20
20
|
python-version:
|
|
21
|
-
- "3.9"
|
|
22
21
|
- "3.10"
|
|
23
22
|
- "3.11"
|
|
24
23
|
- "3.12"
|
|
24
|
+
- "3.13"
|
|
25
|
+
- "3.14"
|
|
25
26
|
pandas-version:
|
|
26
|
-
- "2.1.*"
|
|
27
27
|
- "2.2.*"
|
|
28
|
+
- "2.3.*"
|
|
28
29
|
include:
|
|
29
|
-
- python-version: "3.8"
|
|
30
|
-
pandas-version: "none"
|
|
31
30
|
# https://github.com/pandas-dev/pandas/issues/42509
|
|
32
|
-
- python-version: "pypy3.
|
|
31
|
+
- python-version: "pypy3.11"
|
|
33
32
|
pandas-version: "none"
|
|
34
|
-
# https://github.com/pandas-dev/pandas/issues/
|
|
35
|
-
- python-version: "
|
|
33
|
+
# https://github.com/pandas-dev/pandas/issues/60016
|
|
34
|
+
- python-version: "3.13t"
|
|
36
35
|
pandas-version: "none"
|
|
37
|
-
- python-version: "3.13"
|
|
38
|
-
pandas-version: "2.2.*"
|
|
39
36
|
# https://github.com/pandas-dev/pandas/issues/60016
|
|
40
|
-
- python-version: "3.
|
|
37
|
+
- python-version: "3.14t"
|
|
41
38
|
pandas-version: "none"
|
|
42
|
-
disable-gil: true
|
|
43
39
|
|
|
44
40
|
runs-on: ubuntu-latest
|
|
45
41
|
|
|
@@ -47,7 +43,7 @@ jobs:
|
|
|
47
43
|
PYTHON: ${{ matrix.python-version }}
|
|
48
44
|
|
|
49
45
|
steps:
|
|
50
|
-
- uses: actions/checkout@
|
|
46
|
+
- uses: actions/checkout@v5
|
|
51
47
|
|
|
52
48
|
- name: install rust stable
|
|
53
49
|
uses: dtolnay/rust-toolchain@master
|
|
@@ -61,29 +57,22 @@ jobs:
|
|
|
61
57
|
key: v3
|
|
62
58
|
|
|
63
59
|
- name: set up python
|
|
64
|
-
uses: actions/setup-python@
|
|
60
|
+
uses: actions/setup-python@v6
|
|
65
61
|
if: "${{ !matrix.disable-gil }}"
|
|
66
62
|
with:
|
|
67
63
|
python-version: ${{ matrix.python-version }}
|
|
68
64
|
allow-prereleases: true
|
|
69
65
|
|
|
70
|
-
- name: set up python (free-threaded)
|
|
71
|
-
uses: deadsnakes/action@v3.2.0
|
|
72
|
-
if: "${{ matrix.disable-gil }}"
|
|
73
|
-
with:
|
|
74
|
-
python-version: ${{ matrix.python-version }}
|
|
75
|
-
nogil: ${{ matrix.disable-gil }}
|
|
76
|
-
|
|
77
66
|
- id: cache-py
|
|
78
67
|
name: cache python
|
|
79
68
|
uses: actions/cache@v4
|
|
80
|
-
if: "${{ !matrix.disable-gil }}"
|
|
81
69
|
with:
|
|
82
70
|
path: ${{ env.pythonLocation }}
|
|
83
71
|
key: >
|
|
84
72
|
py
|
|
85
73
|
${{ runner.os }}
|
|
86
|
-
${{
|
|
74
|
+
${{ matrix.python-version }}
|
|
75
|
+
${{ matrix.pandas-version }}
|
|
87
76
|
|
|
88
77
|
- run: |
|
|
89
78
|
if [ ${{ matrix.pandas-version }} == 'none' ]; then
|
|
@@ -105,7 +94,7 @@ jobs:
|
|
|
105
94
|
runs-on: ubuntu-latest
|
|
106
95
|
|
|
107
96
|
steps:
|
|
108
|
-
- uses: actions/checkout@
|
|
97
|
+
- uses: actions/checkout@v5
|
|
109
98
|
|
|
110
99
|
- name: install rust stable
|
|
111
100
|
uses: dtolnay/rust-toolchain@stable
|
|
@@ -115,7 +104,7 @@ jobs:
|
|
|
115
104
|
- name: cache rust
|
|
116
105
|
uses: Swatinem/rust-cache@v2
|
|
117
106
|
|
|
118
|
-
- uses: actions/setup-python@
|
|
107
|
+
- uses: actions/setup-python@v6
|
|
119
108
|
with:
|
|
120
109
|
python-version: "3.13"
|
|
121
110
|
|
|
@@ -155,7 +144,7 @@ jobs:
|
|
|
155
144
|
strategy:
|
|
156
145
|
fail-fast: false
|
|
157
146
|
matrix:
|
|
158
|
-
os: [ubuntu, macos
|
|
147
|
+
os: [ubuntu, macos]
|
|
159
148
|
target: [x86_64, aarch64]
|
|
160
149
|
manylinux: [auto]
|
|
161
150
|
include:
|
|
@@ -163,15 +152,17 @@ jobs:
|
|
|
163
152
|
platform: linux
|
|
164
153
|
- os: windows
|
|
165
154
|
ls: dir
|
|
155
|
+
target: x86_64
|
|
156
|
+
interpreter: 3.10 3.11 3.12 3.13 3.13t
|
|
166
157
|
- os: windows
|
|
167
158
|
ls: dir
|
|
168
159
|
target: i686
|
|
169
160
|
python-architecture: x86
|
|
170
|
-
interpreter: 3.
|
|
161
|
+
interpreter: 3.10 3.11 3.12 3.13 3.13t
|
|
171
162
|
- os: windows
|
|
172
163
|
ls: dir
|
|
173
164
|
target: aarch64
|
|
174
|
-
interpreter: 3.11 3.12 3.13
|
|
165
|
+
interpreter: 3.11 3.12 3.13 3.13t
|
|
175
166
|
- os: ubuntu
|
|
176
167
|
platform: linux
|
|
177
168
|
target: i686
|
|
@@ -181,7 +172,7 @@ jobs:
|
|
|
181
172
|
- os: ubuntu
|
|
182
173
|
platform: linux
|
|
183
174
|
target: armv7
|
|
184
|
-
interpreter: 3.
|
|
175
|
+
interpreter: 3.10 3.11 3.12 3.13 3.13t 3.14 3.14t pypy3.11
|
|
185
176
|
# musllinux
|
|
186
177
|
- os: ubuntu
|
|
187
178
|
platform: linux
|
|
@@ -194,22 +185,18 @@ jobs:
|
|
|
194
185
|
- os: ubuntu
|
|
195
186
|
platform: linux
|
|
196
187
|
target: ppc64le
|
|
197
|
-
interpreter: 3.
|
|
188
|
+
interpreter: 3.10 3.11 3.12 3.13 3.13t 3.14 3.14t pypy3.11
|
|
198
189
|
- os: ubuntu
|
|
199
190
|
platform: linux
|
|
200
191
|
target: s390x
|
|
201
|
-
interpreter: 3.
|
|
202
|
-
exclude:
|
|
203
|
-
# Windows on arm64 only supports Python 3.11+
|
|
204
|
-
- os: windows
|
|
205
|
-
target: aarch64
|
|
192
|
+
interpreter: 3.10 3.11 3.12 3.13 3.13t 3.14 3.14t pypy3.11
|
|
206
193
|
|
|
207
194
|
runs-on: ${{ matrix.os }}-latest
|
|
208
195
|
steps:
|
|
209
|
-
- uses: actions/checkout@
|
|
196
|
+
- uses: actions/checkout@v5
|
|
210
197
|
|
|
211
198
|
- name: set up python
|
|
212
|
-
uses: actions/setup-python@
|
|
199
|
+
uses: actions/setup-python@v6
|
|
213
200
|
with:
|
|
214
201
|
python-version: "3.13"
|
|
215
202
|
architecture: ${{ matrix.python-architecture || 'x64' }}
|
|
@@ -229,7 +216,7 @@ jobs:
|
|
|
229
216
|
with:
|
|
230
217
|
target: ${{ matrix.target }}
|
|
231
218
|
manylinux: ${{ matrix.manylinux || 'auto' }}
|
|
232
|
-
args: --release --out dist --interpreter ${{ matrix.interpreter || '3.
|
|
219
|
+
args: --release --out dist --interpreter ${{ matrix.interpreter || '3.10 3.11 3.12 3.13 3.13t 3.14 3.14t pypy3.11' }}
|
|
233
220
|
rust-toolchain: stable
|
|
234
221
|
|
|
235
222
|
- run: ${{ matrix.ls || 'ls -lh' }} dist/
|
|
@@ -256,7 +243,7 @@ jobs:
|
|
|
256
243
|
|
|
257
244
|
steps:
|
|
258
245
|
- name: Download All Artifacts
|
|
259
|
-
uses: actions/download-artifact@
|
|
246
|
+
uses: actions/download-artifact@v5
|
|
260
247
|
with:
|
|
261
248
|
path: dist
|
|
262
249
|
pattern: wheels-*
|
|
@@ -70,8 +70,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|
|
70
70
|
|
|
71
71
|
[[package]]
|
|
72
72
|
name = "calamine"
|
|
73
|
-
version = "0.
|
|
74
|
-
source = "
|
|
73
|
+
version = "0.30.0"
|
|
74
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
75
|
+
checksum = "a9aeb09f84576a634da713630e11e431a744b91f1f8114c2ff0760189783a8a1"
|
|
75
76
|
dependencies = [
|
|
76
77
|
"atoi_simd",
|
|
77
78
|
"byteorder",
|
|
@@ -170,12 +171,6 @@ dependencies = [
|
|
|
170
171
|
"cfg-if",
|
|
171
172
|
]
|
|
172
173
|
|
|
173
|
-
[[package]]
|
|
174
|
-
name = "crossbeam-utils"
|
|
175
|
-
version = "0.8.21"
|
|
176
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
177
|
-
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
|
178
|
-
|
|
179
174
|
[[package]]
|
|
180
175
|
name = "derive_arbitrary"
|
|
181
176
|
version = "1.4.1"
|
|
@@ -187,17 +182,6 @@ dependencies = [
|
|
|
187
182
|
"syn",
|
|
188
183
|
]
|
|
189
184
|
|
|
190
|
-
[[package]]
|
|
191
|
-
name = "displaydoc"
|
|
192
|
-
version = "0.2.5"
|
|
193
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
194
|
-
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
|
195
|
-
dependencies = [
|
|
196
|
-
"proc-macro2",
|
|
197
|
-
"quote",
|
|
198
|
-
"syn",
|
|
199
|
-
]
|
|
200
|
-
|
|
201
185
|
[[package]]
|
|
202
186
|
name = "encoding_rs"
|
|
203
187
|
version = "0.8.35"
|
|
@@ -246,11 +230,12 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
|
|
246
230
|
|
|
247
231
|
[[package]]
|
|
248
232
|
name = "flate2"
|
|
249
|
-
version = "1.
|
|
233
|
+
version = "1.1.2"
|
|
250
234
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
251
|
-
checksum = "
|
|
235
|
+
checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d"
|
|
252
236
|
dependencies = [
|
|
253
237
|
"crc32fast",
|
|
238
|
+
"libz-rs-sys",
|
|
254
239
|
"miniz_oxide",
|
|
255
240
|
]
|
|
256
241
|
|
|
@@ -344,6 +329,15 @@ version = "0.2.169"
|
|
|
344
329
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
345
330
|
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
|
346
331
|
|
|
332
|
+
[[package]]
|
|
333
|
+
name = "libz-rs-sys"
|
|
334
|
+
version = "0.5.1"
|
|
335
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
336
|
+
checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221"
|
|
337
|
+
dependencies = [
|
|
338
|
+
"zlib-rs",
|
|
339
|
+
]
|
|
340
|
+
|
|
347
341
|
[[package]]
|
|
348
342
|
name = "linux-raw-sys"
|
|
349
343
|
version = "0.4.15"
|
|
@@ -379,9 +373,9 @@ dependencies = [
|
|
|
379
373
|
|
|
380
374
|
[[package]]
|
|
381
375
|
name = "miniz_oxide"
|
|
382
|
-
version = "0.8.
|
|
376
|
+
version = "0.8.9"
|
|
383
377
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
384
|
-
checksum = "
|
|
378
|
+
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
|
385
379
|
dependencies = [
|
|
386
380
|
"adler2",
|
|
387
381
|
]
|
|
@@ -397,9 +391,9 @@ dependencies = [
|
|
|
397
391
|
|
|
398
392
|
[[package]]
|
|
399
393
|
name = "once_cell"
|
|
400
|
-
version = "1.
|
|
394
|
+
version = "1.21.3"
|
|
401
395
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
402
|
-
checksum = "
|
|
396
|
+
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
|
403
397
|
|
|
404
398
|
[[package]]
|
|
405
399
|
name = "portable-atomic"
|
|
@@ -429,9 +423,9 @@ dependencies = [
|
|
|
429
423
|
|
|
430
424
|
[[package]]
|
|
431
425
|
name = "pyo3"
|
|
432
|
-
version = "0.
|
|
426
|
+
version = "0.26.0"
|
|
433
427
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
434
|
-
checksum = "
|
|
428
|
+
checksum = "7ba0117f4212101ee6544044dae45abe1083d30ce7b29c4b5cbdfa2354e07383"
|
|
435
429
|
dependencies = [
|
|
436
430
|
"chrono",
|
|
437
431
|
"indoc",
|
|
@@ -447,20 +441,19 @@ dependencies = [
|
|
|
447
441
|
|
|
448
442
|
[[package]]
|
|
449
443
|
name = "pyo3-build-config"
|
|
450
|
-
version = "0.
|
|
444
|
+
version = "0.26.0"
|
|
451
445
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
452
|
-
checksum = "
|
|
446
|
+
checksum = "4fc6ddaf24947d12a9aa31ac65431fb1b851b8f4365426e182901eabfb87df5f"
|
|
453
447
|
dependencies = [
|
|
454
|
-
"once_cell",
|
|
455
448
|
"python3-dll-a",
|
|
456
449
|
"target-lexicon",
|
|
457
450
|
]
|
|
458
451
|
|
|
459
452
|
[[package]]
|
|
460
453
|
name = "pyo3-ffi"
|
|
461
|
-
version = "0.
|
|
454
|
+
version = "0.26.0"
|
|
462
455
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
463
|
-
checksum = "
|
|
456
|
+
checksum = "025474d3928738efb38ac36d4744a74a400c901c7596199e20e45d98eb194105"
|
|
464
457
|
dependencies = [
|
|
465
458
|
"libc",
|
|
466
459
|
"pyo3-build-config",
|
|
@@ -469,8 +462,7 @@ dependencies = [
|
|
|
469
462
|
[[package]]
|
|
470
463
|
name = "pyo3-file"
|
|
471
464
|
version = "0.13.0"
|
|
472
|
-
source = "
|
|
473
|
-
checksum = "75916300df50dbfa6958ec05fe53473e69474542dac7fd1275aa6869a18a241a"
|
|
465
|
+
source = "git+https://github.com/dimastbk/pyo3-file.git?rev=da8ddb5d774d042555b867dd6571f3ce128bc349#da8ddb5d774d042555b867dd6571f3ce128bc349"
|
|
474
466
|
dependencies = [
|
|
475
467
|
"pyo3",
|
|
476
468
|
"skeptic",
|
|
@@ -478,9 +470,9 @@ dependencies = [
|
|
|
478
470
|
|
|
479
471
|
[[package]]
|
|
480
472
|
name = "pyo3-macros"
|
|
481
|
-
version = "0.
|
|
473
|
+
version = "0.26.0"
|
|
482
474
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
483
|
-
checksum = "
|
|
475
|
+
checksum = "2e64eb489f22fe1c95911b77c44cc41e7c19f3082fc81cce90f657cdc42ffded"
|
|
484
476
|
dependencies = [
|
|
485
477
|
"proc-macro2",
|
|
486
478
|
"pyo3-macros-backend",
|
|
@@ -490,9 +482,9 @@ dependencies = [
|
|
|
490
482
|
|
|
491
483
|
[[package]]
|
|
492
484
|
name = "pyo3-macros-backend"
|
|
493
|
-
version = "0.
|
|
485
|
+
version = "0.26.0"
|
|
494
486
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
495
|
-
checksum = "
|
|
487
|
+
checksum = "100246c0ecf400b475341b8455a9213344569af29a3c841d29270e53102e0fcf"
|
|
496
488
|
dependencies = [
|
|
497
489
|
"heck",
|
|
498
490
|
"proc-macro2",
|
|
@@ -503,7 +495,7 @@ dependencies = [
|
|
|
503
495
|
|
|
504
496
|
[[package]]
|
|
505
497
|
name = "python-calamine"
|
|
506
|
-
version = "0.
|
|
498
|
+
version = "0.5.1"
|
|
507
499
|
dependencies = [
|
|
508
500
|
"calamine",
|
|
509
501
|
"chrono",
|
|
@@ -667,26 +659,6 @@ dependencies = [
|
|
|
667
659
|
"windows-sys",
|
|
668
660
|
]
|
|
669
661
|
|
|
670
|
-
[[package]]
|
|
671
|
-
name = "thiserror"
|
|
672
|
-
version = "2.0.10"
|
|
673
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
674
|
-
checksum = "a3ac7f54ca534db81081ef1c1e7f6ea8a3ef428d2fc069097c079443d24124d3"
|
|
675
|
-
dependencies = [
|
|
676
|
-
"thiserror-impl",
|
|
677
|
-
]
|
|
678
|
-
|
|
679
|
-
[[package]]
|
|
680
|
-
name = "thiserror-impl"
|
|
681
|
-
version = "2.0.10"
|
|
682
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
683
|
-
checksum = "9e9465d30713b56a37ede7185763c3492a91be2f5fa68d958c44e41ab9248beb"
|
|
684
|
-
dependencies = [
|
|
685
|
-
"proc-macro2",
|
|
686
|
-
"quote",
|
|
687
|
-
"syn",
|
|
688
|
-
]
|
|
689
|
-
|
|
690
662
|
[[package]]
|
|
691
663
|
name = "unicase"
|
|
692
664
|
version = "2.8.1"
|
|
@@ -880,21 +852,24 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|
|
880
852
|
|
|
881
853
|
[[package]]
|
|
882
854
|
name = "zip"
|
|
883
|
-
version = "
|
|
855
|
+
version = "4.5.0"
|
|
884
856
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
885
|
-
checksum = "
|
|
857
|
+
checksum = "8835eb39822904d39cb19465de1159e05d371973f0c6df3a365ad50565ddc8b9"
|
|
886
858
|
dependencies = [
|
|
887
859
|
"arbitrary",
|
|
888
860
|
"crc32fast",
|
|
889
|
-
"crossbeam-utils",
|
|
890
|
-
"displaydoc",
|
|
891
861
|
"flate2",
|
|
892
862
|
"indexmap",
|
|
893
863
|
"memchr",
|
|
894
|
-
"thiserror",
|
|
895
864
|
"zopfli",
|
|
896
865
|
]
|
|
897
866
|
|
|
867
|
+
[[package]]
|
|
868
|
+
name = "zlib-rs"
|
|
869
|
+
version = "0.5.1"
|
|
870
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
871
|
+
checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a"
|
|
872
|
+
|
|
898
873
|
[[package]]
|
|
899
874
|
name = "zopfli"
|
|
900
875
|
version = "0.8.1"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "python-calamine"
|
|
3
|
+
version = "0.5.1"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
|
|
7
|
+
[lib]
|
|
8
|
+
name = "python_calamine"
|
|
9
|
+
crate-type = ["cdylib"]
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
calamine = { version = "0.30.0", features = ["dates"] }
|
|
13
|
+
pyo3 = { version = "0.26.0", features = [
|
|
14
|
+
"extension-module",
|
|
15
|
+
"chrono",
|
|
16
|
+
"generate-import-lib",
|
|
17
|
+
] }
|
|
18
|
+
chrono = { version = "0.4.38", features = ["serde"] }
|
|
19
|
+
pyo3-file = { git = "https://github.com/dimastbk/pyo3-file.git", rev = "da8ddb5d774d042555b867dd6571f3ce128bc349" }
|
|
20
|
+
|
|
21
|
+
[build-dependencies]
|
|
22
|
+
pyo3-build-config = "0.26.0"
|
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-calamine
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
6
5
|
Classifier: Programming Language :: Rust
|
|
7
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
8
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
9
6
|
Classifier: Programming Language :: Python :: 3.10
|
|
10
7
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
8
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
9
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
-
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
11
|
Requires-Dist: maturin~=1.0 ; extra == 'dev'
|
|
15
|
-
Requires-Dist: pre-commit~=3
|
|
12
|
+
Requires-Dist: pre-commit~=4.3 ; extra == 'dev'
|
|
16
13
|
Requires-Dist: pytest~=8.0 ; extra == 'dev'
|
|
17
|
-
Requires-Dist: pandas[excel]~=2.
|
|
18
|
-
Requires-Dist: numpy~=1.0 ; extra == 'dev'
|
|
14
|
+
Requires-Dist: pandas[excel]~=2.2 ; extra == 'dev'
|
|
19
15
|
Provides-Extra: dev
|
|
20
16
|
License-File: LICENSE
|
|
21
17
|
Summary: Python binding for Rust's library for reading excel and odf file - calamine
|
|
22
|
-
Home-Page: https://github.com/dimastbk/python-calamine
|
|
23
|
-
Author: Dmitriy <dimastbk@proton.me>
|
|
24
18
|
Author-email: Dmitriy <dimastbk@proton.me>
|
|
25
|
-
License: MIT
|
|
26
|
-
Requires-Python: >=3.
|
|
19
|
+
License-Expression: MIT
|
|
20
|
+
Requires-Python: >=3.10
|
|
27
21
|
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
28
|
-
Project-URL: Source Code, https://github.com/dimastbk/python-calamine
|
|
29
22
|
|
|
30
23
|
# python-calamine
|
|
31
24
|
[](https://pypi.org/project/python-calamine/)
|
|
@@ -79,20 +72,7 @@ workbook = CalamineWorkbook.from_path("file.xlsx").get_sheet_by_name("Sheet1").t
|
|
|
79
72
|
# ]
|
|
80
73
|
```
|
|
81
74
|
|
|
82
|
-
Also, you can use monkeypatch for pandas for use this library as engine in `read_excel()` (only pandas 2.0 and 2.1 are supported).
|
|
83
75
|
Pandas 2.2 and above have built-in support of python-calamine.
|
|
84
|
-
```python
|
|
85
|
-
from pandas import read_excel
|
|
86
|
-
from python_calamine.pandas import pandas_monkeypatch
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
pandas_monkeypatch()
|
|
90
|
-
|
|
91
|
-
read_excel("file.xlsx", engine="calamine")
|
|
92
|
-
# 1 2 3 4 5 6 7
|
|
93
|
-
# 0 1 2 3 4 5 6 7
|
|
94
|
-
# 1 1 2 3 4 5 6 7
|
|
95
|
-
```
|
|
96
76
|
|
|
97
77
|
Also, you can find additional examples in [tests](https://github.com/dimastbk/python-calamine/blob/master/tests/test_base.py).
|
|
98
78
|
|
|
@@ -50,20 +50,7 @@ workbook = CalamineWorkbook.from_path("file.xlsx").get_sheet_by_name("Sheet1").t
|
|
|
50
50
|
# ]
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
Also, you can use monkeypatch for pandas for use this library as engine in `read_excel()` (only pandas 2.0 and 2.1 are supported).
|
|
54
53
|
Pandas 2.2 and above have built-in support of python-calamine.
|
|
55
|
-
```python
|
|
56
|
-
from pandas import read_excel
|
|
57
|
-
from python_calamine.pandas import pandas_monkeypatch
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
pandas_monkeypatch()
|
|
61
|
-
|
|
62
|
-
read_excel("file.xlsx", engine="calamine")
|
|
63
|
-
# 1 2 3 4 5 6 7
|
|
64
|
-
# 0 1 2 3 4 5 6 7
|
|
65
|
-
# 1 1 2 3 4 5 6 7
|
|
66
|
-
```
|
|
67
54
|
|
|
68
55
|
Also, you can find additional examples in [tests](https://github.com/dimastbk/python-calamine/blob/master/tests/test_base.py).
|
|
69
56
|
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-calamine"
|
|
3
|
-
|
|
3
|
+
description = "Python binding for Rust's library for reading excel and odf file - calamine"
|
|
4
|
+
readme = "README.md"
|
|
5
|
+
requires-python = ">=3.10"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
authors = [{ name = "Dmitriy", email = "dimastbk@proton.me" }]
|
|
4
8
|
classifiers = [
|
|
5
9
|
"Development Status :: 4 - Beta",
|
|
6
|
-
"License :: OSI Approved :: MIT License",
|
|
7
10
|
"Programming Language :: Rust",
|
|
8
|
-
"Programming Language :: Python :: 3.8",
|
|
9
|
-
"Programming Language :: Python :: 3.9",
|
|
10
11
|
"Programming Language :: Python :: 3.10",
|
|
11
12
|
"Programming Language :: Python :: 3.11",
|
|
12
13
|
"Programming Language :: Python :: 3.12",
|
|
13
14
|
"Programming Language :: Python :: 3.13",
|
|
15
|
+
"Programming Language :: Python :: 3.14",
|
|
14
16
|
]
|
|
15
|
-
dependencies = ["packaging>=23.1"]
|
|
16
17
|
dynamic = ["version"]
|
|
17
18
|
|
|
18
19
|
[project.optional-dependencies]
|
|
19
20
|
dev = [
|
|
20
21
|
"maturin~=1.0",
|
|
21
|
-
"pre-commit~=3
|
|
22
|
+
"pre-commit~=4.3",
|
|
22
23
|
"pytest~=8.0",
|
|
23
|
-
"pandas[excel]~=2.
|
|
24
|
-
"numpy~=1.0",
|
|
24
|
+
"pandas[excel]~=2.2",
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
[tool.isort]
|
|
@@ -31,7 +31,7 @@ multi_line_output = 3
|
|
|
31
31
|
profile = "black"
|
|
32
32
|
|
|
33
33
|
[tool.mypy]
|
|
34
|
-
python_version = "3.
|
|
34
|
+
python_version = "3.10"
|
|
35
35
|
ignore_missing_imports = false
|
|
36
36
|
disallow_untyped_defs = true
|
|
37
37
|
check_untyped_defs = true
|
|
@@ -8,7 +8,7 @@ use crate::types::{
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
#[pyfunction]
|
|
11
|
-
fn load_workbook(py: Python, path_or_filelike:
|
|
11
|
+
fn load_workbook(py: Python, path_or_filelike: Py<PyAny>) -> PyResult<CalamineWorkbook> {
|
|
12
12
|
CalamineWorkbook::from_object(py, path_or_filelike)
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
use std::convert::From;
|
|
2
2
|
|
|
3
3
|
use calamine::DataType;
|
|
4
|
+
use chrono::Datelike;
|
|
4
5
|
use pyo3::prelude::*;
|
|
5
6
|
|
|
7
|
+
/// https://docs.python.org/3/library/datetime.html#constants
|
|
8
|
+
/// The smallest year number allowed in a date or datetime object. MINYEAR is 1.
|
|
9
|
+
const MINYEAR: i32 = 1;
|
|
10
|
+
|
|
11
|
+
/// The largest year number allowed in a date or datetime object. MAXYEAR is 9999.
|
|
12
|
+
const MAXYEAR: i32 = 9999;
|
|
13
|
+
|
|
6
14
|
#[derive(Debug, Clone)]
|
|
7
15
|
pub enum CellValue {
|
|
8
16
|
Int(i64),
|
|
@@ -16,6 +24,14 @@ pub enum CellValue {
|
|
|
16
24
|
Empty,
|
|
17
25
|
}
|
|
18
26
|
|
|
27
|
+
fn check_year_range<DT: Datelike>(value: DT) -> Option<DT> {
|
|
28
|
+
if value.year() < MINYEAR || value.year() > MAXYEAR {
|
|
29
|
+
None
|
|
30
|
+
} else {
|
|
31
|
+
Some(value)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
19
35
|
impl<'py> IntoPyObject<'py> for CellValue {
|
|
20
36
|
type Target = PyAny;
|
|
21
37
|
type Output = Bound<'py, Self::Target>;
|
|
@@ -64,19 +80,31 @@ where
|
|
|
64
80
|
} else if v < 1.0 {
|
|
65
81
|
value.as_time().map(CellValue::Time)
|
|
66
82
|
} else if v == (v as u64) as f64 {
|
|
67
|
-
value
|
|
83
|
+
value
|
|
84
|
+
.as_date()
|
|
85
|
+
.and_then(check_year_range)
|
|
86
|
+
.map(CellValue::Date)
|
|
68
87
|
} else {
|
|
69
|
-
value
|
|
88
|
+
value
|
|
89
|
+
.as_datetime()
|
|
90
|
+
.and_then(check_year_range)
|
|
91
|
+
.map(CellValue::DateTime)
|
|
70
92
|
}
|
|
71
93
|
.unwrap_or(CellValue::Float(v))
|
|
72
94
|
} else if value.is_datetime_iso() {
|
|
73
95
|
let v = value.get_datetime_iso().unwrap();
|
|
74
96
|
if v.contains('T') {
|
|
75
|
-
value
|
|
97
|
+
value
|
|
98
|
+
.as_datetime()
|
|
99
|
+
.and_then(check_year_range)
|
|
100
|
+
.map(CellValue::DateTime)
|
|
76
101
|
} else if v.contains(':') {
|
|
77
102
|
value.as_time().map(CellValue::Time)
|
|
78
103
|
} else {
|
|
79
|
-
value
|
|
104
|
+
value
|
|
105
|
+
.as_date()
|
|
106
|
+
.and_then(check_year_range)
|
|
107
|
+
.map(CellValue::Date)
|
|
80
108
|
}
|
|
81
109
|
.unwrap_or(CellValue::String(v.to_owned()))
|
|
82
110
|
} else if value.is_duration_iso() {
|
|
@@ -209,12 +209,15 @@ impl CalamineSheet {
|
|
|
209
209
|
Arc::clone(&slf.range)
|
|
210
210
|
};
|
|
211
211
|
|
|
212
|
-
PyList::
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
212
|
+
let py_list = PyList::empty(slf.py());
|
|
213
|
+
|
|
214
|
+
for row in range.rows().take(nrows as usize) {
|
|
215
|
+
let py_row = PyList::new(slf.py(), row.iter().map(<&Data as Into<CellValue>>::into))?;
|
|
216
|
+
|
|
217
|
+
py_list.append(py_row)?;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
Ok(py_list)
|
|
218
221
|
}
|
|
219
222
|
|
|
220
223
|
fn iter_rows(&self) -> CalamineCellIterator {
|
|
@@ -102,7 +102,7 @@ impl CalamineWorkbook {
|
|
|
102
102
|
fn py_from_object(
|
|
103
103
|
_cls: &Bound<'_, PyType>,
|
|
104
104
|
py: Python<'_>,
|
|
105
|
-
path_or_filelike:
|
|
105
|
+
path_or_filelike: Py<PyAny>,
|
|
106
106
|
) -> PyResult<Self> {
|
|
107
107
|
Self::from_object(py, path_or_filelike)
|
|
108
108
|
}
|
|
@@ -112,22 +112,22 @@ impl CalamineWorkbook {
|
|
|
112
112
|
fn py_from_filelike(
|
|
113
113
|
_cls: &Bound<'_, PyType>,
|
|
114
114
|
py: Python<'_>,
|
|
115
|
-
filelike:
|
|
115
|
+
filelike: Py<PyAny>,
|
|
116
116
|
) -> PyResult<Self> {
|
|
117
|
-
py.
|
|
117
|
+
py.detach(|| Self::from_filelike(filelike))
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
#[classmethod]
|
|
121
121
|
#[pyo3(name = "from_path")]
|
|
122
|
-
fn py_from_path(_cls: &Bound<'_, PyType>, py: Python<'_>, path:
|
|
122
|
+
fn py_from_path(_cls: &Bound<'_, PyType>, py: Python<'_>, path: Py<PyAny>) -> PyResult<Self> {
|
|
123
123
|
if let Ok(string_ref) = path.downcast_bound::<PyString>(py) {
|
|
124
124
|
let path = string_ref.to_string_lossy().to_string();
|
|
125
|
-
return py.
|
|
125
|
+
return py.detach(|| Self::from_path(&path));
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
if let Ok(string_ref) = path.extract::<PathBuf>(py) {
|
|
129
129
|
let path = string_ref.to_string_lossy().to_string();
|
|
130
|
-
return py.
|
|
130
|
+
return py.detach(|| Self::from_path(&path));
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
Err(PyTypeError::new_err(""))
|
|
@@ -135,12 +135,12 @@ impl CalamineWorkbook {
|
|
|
135
135
|
|
|
136
136
|
#[pyo3(name = "get_sheet_by_name")]
|
|
137
137
|
fn py_get_sheet_by_name(&mut self, py: Python<'_>, name: &str) -> PyResult<CalamineSheet> {
|
|
138
|
-
py.
|
|
138
|
+
py.detach(|| self.get_sheet_by_name(name))
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
#[pyo3(name = "get_sheet_by_index")]
|
|
142
142
|
fn py_get_sheet_by_index(&mut self, py: Python<'_>, index: usize) -> PyResult<CalamineSheet> {
|
|
143
|
-
py.
|
|
143
|
+
py.detach(|| self.get_sheet_by_index(index))
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
fn close(&mut self) -> PyResult<()> {
|
|
@@ -160,30 +160,30 @@ impl CalamineWorkbook {
|
|
|
160
160
|
|
|
161
161
|
fn __exit__(
|
|
162
162
|
&mut self,
|
|
163
|
-
_exc_type:
|
|
164
|
-
_exc_value:
|
|
165
|
-
_traceback:
|
|
163
|
+
_exc_type: Py<PyAny>,
|
|
164
|
+
_exc_value: Py<PyAny>,
|
|
165
|
+
_traceback: Py<PyAny>,
|
|
166
166
|
) -> PyResult<()> {
|
|
167
167
|
self.close()
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
impl CalamineWorkbook {
|
|
172
|
-
pub fn from_object(py: Python<'_>, path_or_filelike:
|
|
172
|
+
pub fn from_object(py: Python<'_>, path_or_filelike: Py<PyAny>) -> PyResult<Self> {
|
|
173
173
|
if let Ok(string_ref) = path_or_filelike.downcast_bound::<PyString>(py) {
|
|
174
174
|
let path = string_ref.to_string_lossy().to_string();
|
|
175
|
-
return py.
|
|
175
|
+
return py.detach(|| Self::from_path(&path));
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
if let Ok(string_ref) = path_or_filelike.extract::<PathBuf>(py) {
|
|
179
179
|
let path = string_ref.to_string_lossy().to_string();
|
|
180
|
-
return py.
|
|
180
|
+
return py.detach(|| Self::from_path(&path));
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
py.
|
|
183
|
+
py.detach(|| Self::from_filelike(path_or_filelike))
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
pub fn from_filelike(filelike:
|
|
186
|
+
pub fn from_filelike(filelike: Py<PyAny>) -> PyResult<Self> {
|
|
187
187
|
let mut buf = vec![];
|
|
188
188
|
PyFileLikeObject::with_requirements(filelike, true, false, true, false)?
|
|
189
189
|
.read_to_end(&mut buf)?;
|
|
Binary file
|
|
@@ -375,3 +375,10 @@ def test_close_workbook_double():
|
|
|
375
375
|
|
|
376
376
|
with pytest.raises(WorkbookClosed):
|
|
377
377
|
reader.close()
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def test_datetime_overflow():
|
|
381
|
+
reader = CalamineWorkbook.from_path(PATH / "issue139.xlsx")
|
|
382
|
+
|
|
383
|
+
# 2994626.0 = 10099-01-01
|
|
384
|
+
assert reader.get_sheet_by_index(0).to_python() == [["date"], [2994626.0]]
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
from importlib.metadata import version
|
|
2
1
|
from pathlib import Path
|
|
3
2
|
|
|
4
3
|
import pytest
|
|
5
|
-
from packaging.version import Version, parse
|
|
6
4
|
|
|
7
5
|
try:
|
|
8
6
|
import pandas as pd
|
|
@@ -14,17 +12,6 @@ except ImportError:
|
|
|
14
12
|
PATH = Path(__file__).parent / "data"
|
|
15
13
|
|
|
16
14
|
|
|
17
|
-
@pytest.fixture(scope="module", autouse=True)
|
|
18
|
-
def pandas_monkeypatch():
|
|
19
|
-
if parse(version("pandas")) >= Version("2.2.0"):
|
|
20
|
-
yield
|
|
21
|
-
else:
|
|
22
|
-
from python_calamine.pandas import pandas_monkeypatch
|
|
23
|
-
|
|
24
|
-
pandas_monkeypatch()
|
|
25
|
-
yield
|
|
26
|
-
|
|
27
|
-
|
|
28
15
|
@pytest.mark.skipif(not pd, reason="pandas is required")
|
|
29
16
|
def test_ods_pandas(expected_df_ods):
|
|
30
17
|
result = pd.read_excel(PATH / "base.ods", sheet_name="Sheet1", engine="calamine")
|
python_calamine-0.4.0/Cargo.toml
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "python-calamine"
|
|
3
|
-
version = "0.4.0"
|
|
4
|
-
authors = ["Dmitriy <dimastbk@proton.me>"]
|
|
5
|
-
description = "Python binding for Rust's library for reading excel and odf file - calamine"
|
|
6
|
-
edition = "2021"
|
|
7
|
-
homepage = "https://github.com/dimastbk/python-calamine"
|
|
8
|
-
license = "MIT"
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
repository = "https://github.com/dimastbk/python-calamine"
|
|
11
|
-
|
|
12
|
-
[lib]
|
|
13
|
-
name = "python_calamine"
|
|
14
|
-
crate-type = ["cdylib"]
|
|
15
|
-
|
|
16
|
-
[dependencies]
|
|
17
|
-
calamine = { git = "https://github.com/tafia/calamine.git", rev = "5cda5c734661f656bdfb7ac7a1b95e77bf89aa09", features = ["dates"] }
|
|
18
|
-
pyo3 = { version = "0.25.1", features = [
|
|
19
|
-
"extension-module",
|
|
20
|
-
"chrono",
|
|
21
|
-
"generate-import-lib",
|
|
22
|
-
] }
|
|
23
|
-
chrono = { version = "0.4.38", features = ["serde"] }
|
|
24
|
-
pyo3-file = "0.13.0"
|
|
25
|
-
|
|
26
|
-
[build-dependencies]
|
|
27
|
-
pyo3-build-config = "0.25.1"
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from datetime import date, datetime, time, timedelta
|
|
4
|
-
from importlib.metadata import version
|
|
5
|
-
from typing import TYPE_CHECKING, Union, cast
|
|
6
|
-
|
|
7
|
-
import pandas as pd
|
|
8
|
-
from packaging.version import Version, parse
|
|
9
|
-
from pandas._typing import Scalar
|
|
10
|
-
from pandas.compat._optional import import_optional_dependency
|
|
11
|
-
from pandas.core.shared_docs import _shared_docs
|
|
12
|
-
from pandas.io.excel import ExcelFile
|
|
13
|
-
from pandas.io.excel._base import ( # type:ignore[attr-defined] # missing in pandas-stubs
|
|
14
|
-
BaseExcelReader,
|
|
15
|
-
)
|
|
16
|
-
from pandas.util._decorators import ( # type:ignore[attr-defined] # missing in pandas-stubs
|
|
17
|
-
doc,
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
if TYPE_CHECKING:
|
|
21
|
-
from pandas._typing import FilePath, ReadBuffer, StorageOptions
|
|
22
|
-
from python_calamine import CalamineSheet, CalamineWorkbook
|
|
23
|
-
|
|
24
|
-
_CellValueT = Union[int, float, str, bool, time, date, datetime, timedelta]
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
PANDAS_VERSION = parse(version("pandas"))
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class CalamineExcelReader(BaseExcelReader):
|
|
31
|
-
book: CalamineWorkbook
|
|
32
|
-
|
|
33
|
-
@doc(storage_options=_shared_docs["storage_options"])
|
|
34
|
-
def __init__(
|
|
35
|
-
self,
|
|
36
|
-
filepath_or_buffer: FilePath | ReadBuffer[bytes],
|
|
37
|
-
storage_options: StorageOptions | None = None,
|
|
38
|
-
engine_kwargs: dict | None = None,
|
|
39
|
-
) -> None:
|
|
40
|
-
"""
|
|
41
|
-
Reader using calamine engine (xlsx/xls/xlsb/ods).
|
|
42
|
-
|
|
43
|
-
Parameters
|
|
44
|
-
----------
|
|
45
|
-
filepath_or_buffer : str, path to be parsed or
|
|
46
|
-
an open readable stream.
|
|
47
|
-
{storage_options}
|
|
48
|
-
engine_kwargs : dict, optional
|
|
49
|
-
Arbitrary keyword arguments passed to excel engine.
|
|
50
|
-
"""
|
|
51
|
-
import_optional_dependency("python_calamine")
|
|
52
|
-
if PANDAS_VERSION >= Version("2.2.0"):
|
|
53
|
-
raise ValueError("Pandas >= 2.2.0 has builtin support of calamine")
|
|
54
|
-
elif PANDAS_VERSION >= Version("2.1.0"):
|
|
55
|
-
super().__init__(
|
|
56
|
-
filepath_or_buffer,
|
|
57
|
-
storage_options=storage_options,
|
|
58
|
-
engine_kwargs=engine_kwargs,
|
|
59
|
-
)
|
|
60
|
-
elif PANDAS_VERSION >= Version("2.0.0"):
|
|
61
|
-
super().__init__(
|
|
62
|
-
filepath_or_buffer,
|
|
63
|
-
storage_options=storage_options,
|
|
64
|
-
)
|
|
65
|
-
else:
|
|
66
|
-
raise ValueError("Pandas >= 2 is only supported")
|
|
67
|
-
|
|
68
|
-
@property
|
|
69
|
-
def _workbook_class(self) -> type[CalamineWorkbook]:
|
|
70
|
-
from python_calamine import CalamineWorkbook
|
|
71
|
-
|
|
72
|
-
return CalamineWorkbook
|
|
73
|
-
|
|
74
|
-
def load_workbook(
|
|
75
|
-
self,
|
|
76
|
-
filepath_or_buffer: FilePath | ReadBuffer[bytes],
|
|
77
|
-
engine_kwargs: dict | None = None,
|
|
78
|
-
) -> CalamineWorkbook:
|
|
79
|
-
from python_calamine import load_workbook
|
|
80
|
-
|
|
81
|
-
return load_workbook(filepath_or_buffer, **(engine_kwargs or {}))
|
|
82
|
-
|
|
83
|
-
@property
|
|
84
|
-
def sheet_names(self) -> list[str]:
|
|
85
|
-
from python_calamine import SheetTypeEnum
|
|
86
|
-
|
|
87
|
-
return [
|
|
88
|
-
sheet.name
|
|
89
|
-
for sheet in self.book.sheets_metadata
|
|
90
|
-
if sheet.typ == SheetTypeEnum.WorkSheet
|
|
91
|
-
]
|
|
92
|
-
|
|
93
|
-
def get_sheet_by_name(self, name: str) -> CalamineSheet:
|
|
94
|
-
self.raise_if_bad_sheet_by_name(name)
|
|
95
|
-
return self.book.get_sheet_by_name(name)
|
|
96
|
-
|
|
97
|
-
def get_sheet_by_index(self, index: int) -> CalamineSheet:
|
|
98
|
-
self.raise_if_bad_sheet_by_index(index)
|
|
99
|
-
return self.book.get_sheet_by_index(index)
|
|
100
|
-
|
|
101
|
-
def get_sheet_data(
|
|
102
|
-
self, sheet: CalamineSheet, file_rows_needed: int | None = None
|
|
103
|
-
) -> list[list[Scalar]]:
|
|
104
|
-
def _convert_cell(value: _CellValueT) -> Scalar:
|
|
105
|
-
if isinstance(value, float):
|
|
106
|
-
val = int(value)
|
|
107
|
-
if val == value:
|
|
108
|
-
return val
|
|
109
|
-
else:
|
|
110
|
-
return value
|
|
111
|
-
elif isinstance(value, date):
|
|
112
|
-
return pd.Timestamp(value)
|
|
113
|
-
elif isinstance(value, timedelta):
|
|
114
|
-
return pd.Timedelta(value)
|
|
115
|
-
elif isinstance(value, time):
|
|
116
|
-
# cast needed here because Scalar doesn't include datetime.time
|
|
117
|
-
return cast(Scalar, value)
|
|
118
|
-
|
|
119
|
-
return value
|
|
120
|
-
|
|
121
|
-
rows: list[list[_CellValueT]] = sheet.to_python(skip_empty_area=False)
|
|
122
|
-
data: list[list[Scalar]] = []
|
|
123
|
-
|
|
124
|
-
for row in rows:
|
|
125
|
-
data.append([_convert_cell(cell) for cell in row])
|
|
126
|
-
if file_rows_needed is not None and len(data) >= file_rows_needed:
|
|
127
|
-
break
|
|
128
|
-
|
|
129
|
-
return data
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def pandas_monkeypatch() -> None:
|
|
133
|
-
ExcelFile._engines = { # type:ignore[attr-defined] # missing in pandas-stubs
|
|
134
|
-
"calamine": CalamineExcelReader,
|
|
135
|
-
**ExcelFile._engines, # type:ignore[attr-defined] # missing in pandas-stubs
|
|
136
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|