python-calamine 0.3.2__cp312-cp312-win_amd64.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.
- python_calamine/__init__.py +29 -0
- python_calamine/_python_calamine.cp312-win_amd64.pyd +0 -0
- python_calamine/_python_calamine.pyi +182 -0
- python_calamine/pandas.py +136 -0
- python_calamine/py.typed +0 -0
- python_calamine-0.3.2.dist-info/METADATA +117 -0
- python_calamine-0.3.2.dist-info/RECORD +9 -0
- python_calamine-0.3.2.dist-info/WHEEL +4 -0
- python_calamine-0.3.2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from ._python_calamine import (
|
|
2
|
+
CalamineError,
|
|
3
|
+
CalamineSheet,
|
|
4
|
+
CalamineWorkbook,
|
|
5
|
+
PasswordError,
|
|
6
|
+
SheetMetadata,
|
|
7
|
+
SheetTypeEnum,
|
|
8
|
+
SheetVisibleEnum,
|
|
9
|
+
WorkbookClosed,
|
|
10
|
+
WorksheetNotFound,
|
|
11
|
+
XmlError,
|
|
12
|
+
ZipError,
|
|
13
|
+
load_workbook,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = (
|
|
17
|
+
"CalamineError",
|
|
18
|
+
"CalamineSheet",
|
|
19
|
+
"CalamineWorkbook",
|
|
20
|
+
"PasswordError",
|
|
21
|
+
"SheetMetadata",
|
|
22
|
+
"SheetTypeEnum",
|
|
23
|
+
"SheetVisibleEnum",
|
|
24
|
+
"WorksheetNotFound",
|
|
25
|
+
"XmlError",
|
|
26
|
+
"ZipError",
|
|
27
|
+
"WorkbookClosed",
|
|
28
|
+
"load_workbook",
|
|
29
|
+
)
|
|
Binary file
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import datetime
|
|
5
|
+
import enum
|
|
6
|
+
import os
|
|
7
|
+
import types
|
|
8
|
+
import typing
|
|
9
|
+
|
|
10
|
+
@typing.type_check_only
|
|
11
|
+
class ReadBuffer(typing.Protocol):
|
|
12
|
+
def seek(self, __offset: int, __whence: int = ...) -> int: ...
|
|
13
|
+
def read(self, __size: int = ...) -> bytes | None: ...
|
|
14
|
+
|
|
15
|
+
@typing.final
|
|
16
|
+
class SheetTypeEnum(enum.Enum):
|
|
17
|
+
WorkSheet = ...
|
|
18
|
+
DialogSheet = ...
|
|
19
|
+
MacroSheet = ...
|
|
20
|
+
ChartSheet = ...
|
|
21
|
+
Vba = ...
|
|
22
|
+
|
|
23
|
+
@typing.final
|
|
24
|
+
class SheetVisibleEnum(enum.Enum):
|
|
25
|
+
Visible = ...
|
|
26
|
+
Hidden = ...
|
|
27
|
+
VeryHidden = ...
|
|
28
|
+
|
|
29
|
+
@typing.final
|
|
30
|
+
class SheetMetadata:
|
|
31
|
+
name: str
|
|
32
|
+
typ: SheetTypeEnum
|
|
33
|
+
visible: SheetVisibleEnum
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self, name: str, typ: SheetTypeEnum, visible: SheetVisibleEnum
|
|
37
|
+
) -> None: ...
|
|
38
|
+
|
|
39
|
+
@typing.final
|
|
40
|
+
class CalamineSheet:
|
|
41
|
+
name: str
|
|
42
|
+
@property
|
|
43
|
+
def height(self) -> int: ...
|
|
44
|
+
@property
|
|
45
|
+
def width(self) -> int: ...
|
|
46
|
+
@property
|
|
47
|
+
def total_height(self) -> int: ...
|
|
48
|
+
@property
|
|
49
|
+
def total_width(self) -> int: ...
|
|
50
|
+
@property
|
|
51
|
+
def start(self) -> tuple[int, int] | None: ...
|
|
52
|
+
@property
|
|
53
|
+
def end(self) -> tuple[int, int] | None: ...
|
|
54
|
+
def to_python(
|
|
55
|
+
self, skip_empty_area: bool = True, nrows: int | None = None
|
|
56
|
+
) -> list[
|
|
57
|
+
list[
|
|
58
|
+
int
|
|
59
|
+
| float
|
|
60
|
+
| str
|
|
61
|
+
| bool
|
|
62
|
+
| datetime.time
|
|
63
|
+
| datetime.date
|
|
64
|
+
| datetime.datetime
|
|
65
|
+
| datetime.timedelta
|
|
66
|
+
]
|
|
67
|
+
]:
|
|
68
|
+
"""Retunrning data from sheet as list of lists.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
skip_empty_area (bool):
|
|
72
|
+
By default, calamine skips empty rows/cols before data.
|
|
73
|
+
For suppress this behaviour, set `skip_empty_area` to `False`.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def iter_rows(
|
|
77
|
+
self,
|
|
78
|
+
) -> typing.Iterator[
|
|
79
|
+
list[
|
|
80
|
+
int
|
|
81
|
+
| float
|
|
82
|
+
| str
|
|
83
|
+
| bool
|
|
84
|
+
| datetime.time
|
|
85
|
+
| datetime.date
|
|
86
|
+
| datetime.datetime
|
|
87
|
+
| datetime.timedelta
|
|
88
|
+
]
|
|
89
|
+
]:
|
|
90
|
+
"""Retunrning data from sheet as iterator of lists."""
|
|
91
|
+
|
|
92
|
+
@typing.final
|
|
93
|
+
class CalamineWorkbook(contextlib.AbstractContextManager):
|
|
94
|
+
path: str | None
|
|
95
|
+
sheet_names: list[str]
|
|
96
|
+
sheets_metadata: list[SheetMetadata]
|
|
97
|
+
@classmethod
|
|
98
|
+
def from_object(
|
|
99
|
+
cls, path_or_filelike: str | os.PathLike | ReadBuffer
|
|
100
|
+
) -> "CalamineWorkbook":
|
|
101
|
+
"""Determining type of pyobject and reading from it.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
path_or_filelike (str | os.PathLike | ReadBuffer): path to file or IO (must imlpement read/seek methods).
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
def from_path(cls, path: str | os.PathLike) -> "CalamineWorkbook":
|
|
109
|
+
"""Reading file from path.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
path (str | os.PathLike): path to file.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
@classmethod
|
|
116
|
+
def from_filelike(cls, filelike: ReadBuffer) -> "CalamineWorkbook":
|
|
117
|
+
"""Reading file from IO.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
filelike : IO (must imlpement read/seek methods).
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
def close(self) -> None:
|
|
124
|
+
"""Close the workbook.
|
|
125
|
+
|
|
126
|
+
Drop internal rust structure from workbook (and close the file under the hood).
|
|
127
|
+
`get_sheet_by_name`/`get_sheet_by_index` will raise WorkbookClosed after calling that method.
|
|
128
|
+
|
|
129
|
+
Raises:
|
|
130
|
+
WorkbookClosed: If workbook already closed.
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
def __enter__(self) -> "CalamineWorkbook": ...
|
|
134
|
+
def __exit__(
|
|
135
|
+
self,
|
|
136
|
+
exc_type: type[BaseException] | None,
|
|
137
|
+
exc_val: BaseException | None,
|
|
138
|
+
exc_tb: types.TracebackType | None,
|
|
139
|
+
) -> None: ...
|
|
140
|
+
def get_sheet_by_name(self, name: str) -> CalamineSheet:
|
|
141
|
+
"""Get worksheet by name.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
name(str): name of worksheet
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
CalamineSheet
|
|
148
|
+
|
|
149
|
+
Raises:
|
|
150
|
+
WorkbookClosed: If workbook already closed.
|
|
151
|
+
WorksheetNotFound: If worksheet not found in workbook.
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
def get_sheet_by_index(self, index: int) -> CalamineSheet:
|
|
155
|
+
"""Get worksheet by index.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
index(int): index of worksheet
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
CalamineSheet
|
|
162
|
+
|
|
163
|
+
Raises:
|
|
164
|
+
WorkbookClosed: If workbook already closed.
|
|
165
|
+
WorksheetNotFound: If worksheet not found in workbook.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
class CalamineError(Exception): ...
|
|
169
|
+
class PasswordError(CalamineError): ...
|
|
170
|
+
class WorksheetNotFound(CalamineError): ...
|
|
171
|
+
class XmlError(CalamineError): ...
|
|
172
|
+
class ZipError(CalamineError): ...
|
|
173
|
+
class WorkbookClosed(CalamineError): ...
|
|
174
|
+
|
|
175
|
+
def load_workbook(
|
|
176
|
+
path_or_filelike: str | os.PathLike | ReadBuffer,
|
|
177
|
+
) -> CalamineWorkbook:
|
|
178
|
+
"""Determining type of pyobject and reading from it.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
path_or_filelike (str | os.PathLike | ReadBuffer): path to file or IO (must imlpement read/seek methods).
|
|
182
|
+
"""
|
|
@@ -0,0 +1,136 @@
|
|
|
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
|
+
}
|
python_calamine/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-calamine
|
|
3
|
+
Version: 0.3.2
|
|
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
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Requires-Dist: packaging>=23.1
|
|
14
|
+
Requires-Dist: maturin~=1.0 ; extra == 'dev'
|
|
15
|
+
Requires-Dist: pre-commit~=3.0 ; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest~=8.0 ; extra == 'dev'
|
|
17
|
+
Requires-Dist: pandas[excel]~=2.0 ; extra == 'dev'
|
|
18
|
+
Requires-Dist: numpy~=1.0 ; extra == 'dev'
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
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
|
+
Author-email: Dmitriy <dimastbk@proton.me>
|
|
25
|
+
License: MIT
|
|
26
|
+
Requires-Python: >=3.8
|
|
27
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
28
|
+
Project-URL: Source Code, https://github.com/dimastbk/python-calamine
|
|
29
|
+
|
|
30
|
+
# python-calamine
|
|
31
|
+
[](https://pypi.org/project/python-calamine/)
|
|
32
|
+
[](https://anaconda.org/conda-forge/python-calamine)
|
|
33
|
+

|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Python binding for beautiful Rust's library for reading excel and odf file - [calamine](https://github.com/tafia/calamine).
|
|
37
|
+
|
|
38
|
+
### Is used
|
|
39
|
+
* [calamine](https://github.com/tafia/calamine)
|
|
40
|
+
* [pyo3](https://github.com/PyO3/pyo3)
|
|
41
|
+
* [maturin](https://github.com/PyO3/maturin)
|
|
42
|
+
|
|
43
|
+
### Installation
|
|
44
|
+
Pypi:
|
|
45
|
+
```
|
|
46
|
+
pip install python-calamine
|
|
47
|
+
```
|
|
48
|
+
Conda:
|
|
49
|
+
```
|
|
50
|
+
conda install -c conda-forge python-calamine
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Example
|
|
54
|
+
```python
|
|
55
|
+
from python_calamine import CalamineWorkbook
|
|
56
|
+
|
|
57
|
+
workbook = CalamineWorkbook.from_path("file.xlsx")
|
|
58
|
+
workbook.sheet_names
|
|
59
|
+
# ["Sheet1", "Sheet2"]
|
|
60
|
+
|
|
61
|
+
workbook.get_sheet_by_name("Sheet1").to_python()
|
|
62
|
+
# [
|
|
63
|
+
# ["1", "2", "3", "4", "5", "6", "7"],
|
|
64
|
+
# ["1", "2", "3", "4", "5", "6", "7"],
|
|
65
|
+
# ["1", "2", "3", "4", "5", "6", "7"],
|
|
66
|
+
# ]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
By default, calamine skips empty rows/cols before data. For suppress this behaviour, set `skip_empty_area` to `False`.
|
|
70
|
+
```python
|
|
71
|
+
from python_calamine import CalamineWorkbook
|
|
72
|
+
|
|
73
|
+
workbook = CalamineWorkbook.from_path("file.xlsx").get_sheet_by_name("Sheet1").to_python(skip_empty_area=False)
|
|
74
|
+
# [
|
|
75
|
+
# [", ", ", ", ", ", "],
|
|
76
|
+
# ["1", "2", "3", "4", "5", "6", "7"],
|
|
77
|
+
# ["1", "2", "3", "4", "5", "6", "7"],
|
|
78
|
+
# ["1", "2", "3", "4", "5", "6", "7"],
|
|
79
|
+
# ]
|
|
80
|
+
```
|
|
81
|
+
|
|
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
|
+
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
|
+
|
|
97
|
+
Also, you can find additional examples in [tests](https://github.com/dimastbk/python-calamine/blob/master/tests/test_base.py).
|
|
98
|
+
|
|
99
|
+
### Development
|
|
100
|
+
|
|
101
|
+
You'll need rust [installed](https://rustup.rs/).
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
# clone this repo or your fork
|
|
105
|
+
git clone git@github.com:dimastbk/python-calamine.git
|
|
106
|
+
cd python-calamine
|
|
107
|
+
# create a new virtual env
|
|
108
|
+
python3 -m venv env
|
|
109
|
+
source env/bin/activate
|
|
110
|
+
# install dev dependencies and install python-calamine
|
|
111
|
+
pip install -e .[dev]
|
|
112
|
+
# lint code
|
|
113
|
+
pre-commit run --all-files
|
|
114
|
+
# test code
|
|
115
|
+
pytest
|
|
116
|
+
```
|
|
117
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
python_calamine-0.3.2.dist-info/METADATA,sha256=aOKwJP8J3tnHw8OEmtvCAuZW8MTsW_8UKBcDZP0CIag,3960
|
|
2
|
+
python_calamine-0.3.2.dist-info/WHEEL,sha256=jABKVkLC9kJr8mi_er5jOqpiQUjARSLXDUIIxDqsS50,96
|
|
3
|
+
python_calamine-0.3.2.dist-info/licenses/LICENSE,sha256=cYURXgSnjCTOT2jQ_McTGn-AhDycRqzJa11QzR38Sn4,1086
|
|
4
|
+
python_calamine/pandas.py,sha256=QL-cy_9TMEsjb4bRCNB40tWGPPYlBmUBwEmKBFFuTGc,4734
|
|
5
|
+
python_calamine/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
python_calamine/_python_calamine.pyi,sha256=nPoUpA4zWdJvoBpX8SGmxVx8X1b8EjLYkbsD5ZyPOGA,4973
|
|
7
|
+
python_calamine/__init__.py,sha256=evxSwIkpatTkygn2mRmWUYPslvdj08q_pNkayyyptfI,560
|
|
8
|
+
python_calamine/_python_calamine.cp312-win_amd64.pyd,sha256=ICD7Zxg7JhiIyWXzKtuPjApSrl7F62jjd2AxR1LwBjE,1478656
|
|
9
|
+
python_calamine-0.3.2.dist-info/RECORD,,
|
|
@@ -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.
|