python-calamine 0.1.7__cp312-none-win_arm64.whl

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.
@@ -0,0 +1,19 @@
1
+ from ._python_calamine import (
2
+ CalamineError,
3
+ CalamineSheet,
4
+ CalamineWorkbook,
5
+ SheetMetadata,
6
+ SheetTypeEnum,
7
+ SheetVisibleEnum,
8
+ load_workbook,
9
+ )
10
+
11
+ __all__ = (
12
+ "CalamineError",
13
+ "CalamineSheet",
14
+ "CalamineWorkbook",
15
+ "SheetMetadata",
16
+ "SheetTypeEnum",
17
+ "SheetVisibleEnum",
18
+ "load_workbook",
19
+ )
@@ -0,0 +1,109 @@
1
+ from __future__ import annotations
2
+
3
+ import enum
4
+ from datetime import date, datetime, time, timedelta
5
+ from os import PathLike
6
+ from typing import Protocol
7
+
8
+ ValueT = int | float | str | bool | time | date | datetime | timedelta
9
+
10
+ class ReadBuffer(Protocol):
11
+ def seek(self) -> int: ...
12
+ def read(self) -> bytes: ...
13
+
14
+ class SheetTypeEnum(enum.Enum):
15
+ WorkSheet = ...
16
+ DialogSheet = ...
17
+ MacroSheet = ...
18
+ ChartSheet = ...
19
+ VBA = ...
20
+
21
+ class SheetVisibleEnum(enum.Enum):
22
+ Visible = ...
23
+ Hidden = ...
24
+ VeryHidden = ...
25
+
26
+ class SheetMetadata:
27
+ name: str
28
+ typ: SheetTypeEnum
29
+ visible: SheetVisibleEnum
30
+
31
+ def __init__(
32
+ self, name: str, typ: SheetTypeEnum, visible: SheetVisibleEnum
33
+ ) -> None: ...
34
+
35
+ class CalamineSheet:
36
+ name: str
37
+ @property
38
+ def height(self) -> int: ...
39
+ @property
40
+ def width(self) -> int: ...
41
+ @property
42
+ def total_height(self) -> int: ...
43
+ @property
44
+ def total_width(self) -> int: ...
45
+ @property
46
+ def start(self) -> tuple[int, int] | None: ...
47
+ @property
48
+ def end(self) -> tuple[int, int] | None: ...
49
+ def to_python(
50
+ self, skip_empty_area: bool = True, nrows: int | None = None
51
+ ) -> list[list[ValueT]]:
52
+ """Retunrning data from sheet as list of lists.
53
+
54
+ Parameters
55
+ ----------
56
+ skip_empty_area : bool
57
+ By default, calamine skips empty rows/cols before data.
58
+ For suppress this behaviour, set `skip_empty_area` to `False`.
59
+ """
60
+
61
+ class CalamineWorkbook:
62
+ path: str | None
63
+ sheet_names: list[str]
64
+ sheets_metadata: list[SheetMetadata]
65
+ @classmethod
66
+ def from_object(
67
+ cls, path_or_filelike: str | PathLike | ReadBuffer
68
+ ) -> "CalamineWorkbook":
69
+ """Determining type of pyobject and reading from it.
70
+
71
+ Parameters
72
+ ----------
73
+ path_or_filelike :
74
+ - path (string),
75
+ - pathlike (pathlib.Path),
76
+ - IO (must imlpement read/seek methods).
77
+ """
78
+ @classmethod
79
+ def from_path(cls, path: str) -> "CalamineWorkbook":
80
+ """Reading file from path.
81
+
82
+ Parameters
83
+ ----------
84
+ path : path (string)."""
85
+ @classmethod
86
+ def from_filelike(cls, filelike: ReadBuffer) -> "CalamineWorkbook":
87
+ """Reading file from IO.
88
+
89
+ Parameters
90
+ ----------
91
+ filelike : IO (must imlpement read/seek methods).
92
+ """
93
+ def get_sheet_by_name(self, name: str) -> CalamineSheet: ...
94
+ def get_sheet_by_index(self, index: int) -> CalamineSheet: ...
95
+
96
+ class CalamineError(Exception): ...
97
+
98
+ def load_workbook(
99
+ path_or_filelike: str | PathLike | ReadBuffer,
100
+ ) -> CalamineWorkbook:
101
+ """Determining type of pyobject and reading from it.
102
+
103
+ Parameters
104
+ ----------
105
+ path_or_filelike :
106
+ - path (string),
107
+ - pathlike (pathlib.Path),
108
+ - IO (must imlpement read/seek methods).
109
+ """
@@ -0,0 +1,130 @@
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 BaseExcelReader
14
+ from pandas.util._decorators import doc
15
+
16
+ if TYPE_CHECKING:
17
+ from pandas._typing import FilePath, ReadBuffer, StorageOptions
18
+ from python_calamine import CalamineSheet, CalamineWorkbook
19
+
20
+ _CellValueT = Union[int, float, str, bool, time, date, datetime, timedelta]
21
+
22
+
23
+ PANDAS_VERSION = parse(version("pandas"))
24
+
25
+
26
+ class CalamineExcelReader(BaseExcelReader):
27
+ book: CalamineWorkbook
28
+
29
+ @doc(storage_options=_shared_docs["storage_options"])
30
+ def __init__(
31
+ self,
32
+ filepath_or_buffer: FilePath | ReadBuffer[bytes],
33
+ storage_options: StorageOptions | None = None,
34
+ engine_kwargs: dict | None = None,
35
+ ) -> None:
36
+ """
37
+ Reader using calamine engine (xlsx/xls/xlsb/ods).
38
+
39
+ Parameters
40
+ ----------
41
+ filepath_or_buffer : str, path to be parsed or
42
+ an open readable stream.
43
+ {storage_options}
44
+ engine_kwargs : dict, optional
45
+ Arbitrary keyword arguments passed to excel engine.
46
+ """
47
+ import_optional_dependency("python_calamine")
48
+ if PANDAS_VERSION >= Version("2.1.0"):
49
+ super().__init__(
50
+ filepath_or_buffer,
51
+ storage_options=storage_options,
52
+ engine_kwargs=engine_kwargs,
53
+ )
54
+ elif PANDAS_VERSION >= Version("2.0.0"):
55
+ super().__init__(
56
+ filepath_or_buffer,
57
+ storage_options=storage_options,
58
+ )
59
+ else:
60
+ raise ValueError("Pandas >= 2 is only supported")
61
+
62
+ @property
63
+ def _workbook_class(self) -> type[CalamineWorkbook]:
64
+ from python_calamine import CalamineWorkbook
65
+
66
+ return CalamineWorkbook
67
+
68
+ def load_workbook(
69
+ self,
70
+ filepath_or_buffer: FilePath | ReadBuffer[bytes],
71
+ engine_kwargs: dict | None = None,
72
+ ) -> CalamineWorkbook:
73
+ from python_calamine import load_workbook
74
+
75
+ return load_workbook(filepath_or_buffer, **(engine_kwargs or {}))
76
+
77
+ @property
78
+ def sheet_names(self) -> list[str]:
79
+ from python_calamine import SheetTypeEnum
80
+
81
+ return [
82
+ sheet.name
83
+ for sheet in self.book.sheets_metadata
84
+ if sheet.typ == SheetTypeEnum.WorkSheet
85
+ ]
86
+
87
+ def get_sheet_by_name(self, name: str) -> CalamineSheet:
88
+ self.raise_if_bad_sheet_by_name(name)
89
+ return self.book.get_sheet_by_name(name)
90
+
91
+ def get_sheet_by_index(self, index: int) -> CalamineSheet:
92
+ self.raise_if_bad_sheet_by_index(index)
93
+ return self.book.get_sheet_by_index(index)
94
+
95
+ def get_sheet_data(
96
+ self, sheet: CalamineSheet, file_rows_needed: int | None = None
97
+ ) -> list[list[Scalar]]:
98
+ def _convert_cell(value: _CellValueT) -> Scalar:
99
+ if isinstance(value, float):
100
+ val = int(value)
101
+ if val == value:
102
+ return val
103
+ else:
104
+ return value
105
+ elif isinstance(value, date):
106
+ return pd.Timestamp(value)
107
+ elif isinstance(value, timedelta):
108
+ return pd.Timedelta(value)
109
+ elif isinstance(value, time):
110
+ # cast needed here because Scalar doesn't include datetime.time
111
+ return cast(Scalar, value)
112
+
113
+ return value
114
+
115
+ rows: list[list[_CellValueT]] = sheet.to_python(skip_empty_area=False)
116
+ data: list[list[Scalar]] = []
117
+
118
+ for row in rows:
119
+ data.append([_convert_cell(cell) for cell in row])
120
+ if file_rows_needed is not None and len(data) >= file_rows_needed:
121
+ break
122
+
123
+ return data
124
+
125
+
126
+ def pandas_monkeypatch():
127
+ ExcelFile._engines = {
128
+ "calamine": CalamineExcelReader,
129
+ **ExcelFile._engines,
130
+ }
File without changes
@@ -0,0 +1,80 @@
1
+ Metadata-Version: 2.1
2
+ Name: python-calamine
3
+ Version: 0.1.7
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: License :: OSI Approved :: MIT License
6
+ Classifier: Programming Language :: Rust
7
+ Classifier: Programming Language :: Python :: 3.8
8
+ Classifier: Programming Language :: Python :: 3.9
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ License-File: LICENSE
13
+ Summary: Python binding for Rust's library for reading excel and odf file - calamine
14
+ Home-Page: https://github.com/dimastbk/python-calamine
15
+ Author: Dmitriy <dimastbk@proton.me>
16
+ Author-email: Dmitriy <dimastbk@proton.me>
17
+ License: MIT
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
20
+ Project-URL: Source Code, https://github.com/dimastbk/python-calamine
21
+
22
+ # python-calamine
23
+
24
+ Python binding for beautiful Rust's library for reading excel and odf file - [calamine](https://github.com/tafia/calamine).
25
+
26
+ ### Is used
27
+ * [calamine](https://github.com/tafia/calamine)
28
+ * [pyo3](https://github.com/PyO3/pyo3)
29
+ * [maturin](https://github.com/PyO3/maturin)
30
+
31
+ ### Installation
32
+ ```
33
+ pip install python-calamine
34
+ ```
35
+
36
+ ### Example
37
+ ```python
38
+ from python_calamine import CalamineWorkbook
39
+
40
+ workbook = CalamineWorkbook.from_path("file.xlsx")
41
+ workbook.sheet_names
42
+ # ["Sheet1", "Sheet2"]
43
+
44
+ workbook.get_sheet_by_name("Sheet1").to_python()
45
+ # [
46
+ # ["1", "2", "3", "4", "5", "6", "7"],
47
+ # ["1", "2", "3", "4", "5", "6", "7"],
48
+ # ["1", "2", "3", "4", "5", "6", "7"],
49
+ # ]
50
+ ```
51
+
52
+ By default, calamine skips empty rows/cols before data. For suppress this behaviour, set `skip_empty_area` to `False`.
53
+ ```python
54
+ from python_calamine import CalamineWorkbook
55
+
56
+ workbook = CalamineWorkbook.from_path("file.xlsx").get_sheet_by_name("Sheet1").to_python(skip_empty_area=False)
57
+ # [
58
+ # [", ", ", ", ", ", "],
59
+ # ["1", "2", "3", "4", "5", "6", "7"],
60
+ # ["1", "2", "3", "4", "5", "6", "7"],
61
+ # ["1", "2", "3", "4", "5", "6", "7"],
62
+ # ]
63
+ ```
64
+
65
+ Also, you can use monkeypatch for pandas for use this library as engine in `read_excel()` (only pandas 2 is supported).
66
+ ```python
67
+ from pandas import read_excel
68
+ from python_calamine.pandas import pandas_monkeypatch
69
+
70
+
71
+ pandas_monkeypatch()
72
+
73
+ read_excel("file.xlsx", engine="calamine")
74
+ # 1 2 3 4 5 6 7
75
+ # 0 1 2 3 4 5 6 7
76
+ # 1 1 2 3 4 5 6 7
77
+ ```
78
+
79
+ Also, you can find additional examples in [tests](https://github.com/dimastbk/python-calamine/blob/master/tests/test_base.py).
80
+
@@ -0,0 +1,9 @@
1
+ python_calamine-0.1.7.dist-info/METADATA,sha256=QESuJJ-8K7Gqk95uC5wvf6uWBcp1TsNwrn-Z3KEz_S0,2623
2
+ python_calamine-0.1.7.dist-info/WHEEL,sha256=z3IPjWyGO6p4Az1tcoMrLL5HPYO0qjHypnwneND7UIE,95
3
+ python_calamine-0.1.7.dist-info/license_files/LICENSE,sha256=cYURXgSnjCTOT2jQ_McTGn-AhDycRqzJa11QzR38Sn4,1086
4
+ python_calamine/pandas.py,sha256=37yhE0Ls_PPXkxxIWY1YQghwaVkGfCYUjX5zoAneVoE,4353
5
+ python_calamine/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ python_calamine/_python_calamine.pyi,sha256=Esjev_wvxbLvhPkNDBfU5UpwgplZuiltG_Ojx7ZVWDQ,3011
7
+ python_calamine/__init__.py,sha256=zRCiu_0Q6NABLKqzK7QW2Ap7uTpJ83VxV7UpBF9Z4Yg,360
8
+ python_calamine/_python_calamine.cp312-win_arm64.pyd,sha256=WtkKroC9BGVdPt3KMdvJaUhBb-8GWuC8QJK0WUQ_cZs,1199104
9
+ python_calamine-0.1.7.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.3.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp312-none-win_arm64
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 dimastbk
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.