6
6
time ,
7
7
)
8
8
from tempfile import NamedTemporaryFile
9
- from typing import Union
9
+ from typing import (
10
+ Union ,
11
+ cast ,
12
+ )
10
13
11
14
from pandas ._typing import (
12
15
FilePath ,
15
18
StorageOptions ,
16
19
)
17
20
from pandas .compat ._optional import import_optional_dependency
21
+ from pandas .util ._decorators import doc
18
22
19
23
import pandas as pd
24
+ from pandas .core .shared_docs import _shared_docs
20
25
21
26
from pandas .io .common import stringify_path
22
27
from pandas .io .excel ._base import (
27
32
ValueT = Union [int , float , str , bool , time , date , datetime ]
28
33
29
34
30
- class __calamine__ :
31
- pass
32
-
33
-
34
35
class CalamineExcelReader (BaseExcelReader ):
35
- book : str
36
36
_sheet_names : list [str ] | None = None
37
37
38
+ @doc (storage_options = _shared_docs ["storage_options" ])
38
39
def __init__ (
39
40
self ,
40
41
filepath_or_buffer : FilePath | ReadBuffer [bytes ],
41
42
storage_options : StorageOptions = None ,
42
43
) -> None :
44
+ """
45
+ Reader using calamine engine (xlsx/xls/xlsb/ods).
46
+
47
+ Parameters
48
+ ----------
49
+ filepath_or_buffer : str, path to be parsed or
50
+ an open readable stream.
51
+ {storage_options}
52
+ """
43
53
import_optional_dependency ("python_calamine" )
44
54
super ().__init__ (filepath_or_buffer , storage_options = storage_options )
45
55
46
56
@property
47
- def _workbook_class (self ) -> type [ __calamine__ ] :
48
- return __calamine__
57
+ def _workbook_class (self ):
58
+ from python_calamine import CalamineReader
49
59
50
- def load_workbook (self , filepath_or_buffer ) -> str :
60
+ return CalamineReader
61
+
62
+ def load_workbook (self , filepath_or_buffer : FilePath | ReadBuffer [bytes ]):
51
63
if hasattr (filepath_or_buffer , "read" ) and hasattr (filepath_or_buffer , "seek" ):
64
+ filepath_or_buffer = cast (ReadBuffer , filepath_or_buffer )
52
65
ext = inspect_excel_format (filepath_or_buffer )
53
66
with NamedTemporaryFile (suffix = f".{ ext } " , delete = False ) as tmp_file :
54
67
filepath_or_buffer .seek (0 )
@@ -59,29 +72,24 @@ def load_workbook(self, filepath_or_buffer) -> str:
59
72
60
73
assert isinstance (filepath_or_buffer , str )
61
74
62
- from python_calamine import get_sheet_names
75
+ from python_calamine import CalamineReader
63
76
64
- self ._sheet_names = get_sheet_names (filepath_or_buffer )
65
- return filepath_or_buffer
77
+ return CalamineReader .from_path (filepath_or_buffer )
66
78
67
79
@property
68
80
def sheet_names (self ) -> list [str ]:
69
- from python_calamine import get_sheet_names
70
-
71
- if self ._sheet_names is None :
72
- self ._sheet_names = get_sheet_names (self .book )
73
- return self ._sheet_names
81
+ return self .book .sheet_names # pyright: ignore
74
82
75
- def get_sheet_by_name (self , name : str ) -> int :
83
+ def get_sheet_by_name (self , name : str ):
76
84
self .raise_if_bad_sheet_by_name (name )
77
- return self .sheet_names . index (name )
85
+ return self .book . get_sheet_by_name (name ) # pyright: ignore
78
86
79
- def get_sheet_by_index (self , index : int ) -> int :
87
+ def get_sheet_by_index (self , index : int ):
80
88
self .raise_if_bad_sheet_by_index (index )
81
- return index
89
+ return self . book . get_sheet_by_index ( index ) # pyright: ignore
82
90
83
91
def get_sheet_data (
84
- self , sheet : int , file_rows_needed : int | None = None
92
+ self , sheet , file_rows_needed : int | None = None
85
93
) -> list [list [Scalar ]]:
86
94
def _convert_cell (value : ValueT ) -> Scalar :
87
95
if isinstance (value , float ):
@@ -97,9 +105,7 @@ def _convert_cell(value: ValueT) -> Scalar:
97
105
98
106
return value
99
107
100
- from python_calamine import get_sheet_data
101
-
102
- rows = get_sheet_data (self .book , sheet , skip_empty_area = False )
108
+ rows : list [list [ValueT ]] = sheet .to_python (skip_empty_area = False )
103
109
data : list [list [Scalar ]] = []
104
110
105
111
for row in rows :
0 commit comments