Skip to content

Commit e69a051

Browse files
authored
TYP: misc IO return types (#57228)
* TYP: misc IO return types * isort
1 parent cb16bb0 commit e69a051

File tree

17 files changed

+91
-45
lines changed

17 files changed

+91
-45
lines changed

pandas/_typing.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,3 +529,6 @@ def closed(self) -> bool:
529529
Callable[[HashableT], bool],
530530
None,
531531
]
532+
533+
# maintaine the sub-type of any hashable sequence
534+
SequenceT = TypeVar("SequenceT", bound=Sequence[Hashable])

pandas/io/excel/_openpyxl.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
if TYPE_CHECKING:
2727
from openpyxl import Workbook
2828
from openpyxl.descriptors.serialisable import Serialisable
29+
from openpyxl.styles import Fill
2930

3031
from pandas._typing import (
3132
ExcelWriterIfSheetExists,
@@ -244,7 +245,7 @@ def _convert_to_stop(cls, stop_seq):
244245
return map(cls._convert_to_color, stop_seq)
245246

246247
@classmethod
247-
def _convert_to_fill(cls, fill_dict: dict[str, Any]):
248+
def _convert_to_fill(cls, fill_dict: dict[str, Any]) -> Fill:
248249
"""
249250
Convert ``fill_dict`` to an openpyxl v2 Fill object.
250251

pandas/io/formats/excel.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,9 @@ def build_border(
284284
for side in ["top", "right", "bottom", "left"]
285285
}
286286

287-
def _border_style(self, style: str | None, width: str | None, color: str | None):
287+
def _border_style(
288+
self, style: str | None, width: str | None, color: str | None
289+
) -> str | None:
288290
# convert styles and widths to openxml, one of:
289291
# 'dashDot'
290292
# 'dashDotDot'

pandas/io/formats/format.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,7 +1346,9 @@ def get_result_as_array(self) -> np.ndarray:
13461346
the parameters given at initialisation, as a numpy array
13471347
"""
13481348

1349-
def format_with_na_rep(values: ArrayLike, formatter: Callable, na_rep: str):
1349+
def format_with_na_rep(
1350+
values: ArrayLike, formatter: Callable, na_rep: str
1351+
) -> np.ndarray:
13501352
mask = isna(values)
13511353
formatted = np.array(
13521354
[
@@ -1358,7 +1360,7 @@ def format_with_na_rep(values: ArrayLike, formatter: Callable, na_rep: str):
13581360

13591361
def format_complex_with_na_rep(
13601362
values: ArrayLike, formatter: Callable, na_rep: str
1361-
):
1363+
) -> np.ndarray:
13621364
real_values = np.real(values).ravel() # type: ignore[arg-type]
13631365
imag_values = np.imag(values).ravel() # type: ignore[arg-type]
13641366
real_mask, imag_mask = isna(real_values), isna(imag_values)

pandas/io/formats/info.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ def dtype_counts(self) -> Mapping[str, int]:
392392

393393
@property
394394
@abstractmethod
395-
def non_null_counts(self) -> Sequence[int]:
395+
def non_null_counts(self) -> list[int] | Series:
396396
"""Sequence of non-null counts for all columns or column (if series)."""
397397

398398
@property
@@ -486,7 +486,7 @@ def col_count(self) -> int:
486486
return len(self.ids)
487487

488488
@property
489-
def non_null_counts(self) -> Sequence[int]:
489+
def non_null_counts(self) -> Series:
490490
"""Sequence of non-null counts for all columns or column (if series)."""
491491
return self.data.count()
492492

@@ -546,7 +546,7 @@ def render(
546546
printer.to_buffer(buf)
547547

548548
@property
549-
def non_null_counts(self) -> Sequence[int]:
549+
def non_null_counts(self) -> list[int]:
550550
return [self.data.count()]
551551

552552
@property
@@ -750,7 +750,7 @@ def memory_usage_string(self) -> str:
750750
return self.info.memory_usage_string
751751

752752
@property
753-
def non_null_counts(self) -> Sequence[int]:
753+
def non_null_counts(self) -> list[int] | Series:
754754
return self.info.non_null_counts
755755

756756
def add_object_type_line(self) -> None:

pandas/io/formats/style.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3827,7 +3827,7 @@ def _background_gradient(
38273827
vmax: float | None = None,
38283828
gmap: Sequence | np.ndarray | DataFrame | Series | None = None,
38293829
text_only: bool = False,
3830-
):
3830+
) -> list[str] | DataFrame:
38313831
"""
38323832
Color background in a range according to the data or a gradient map
38333833
"""

pandas/io/formats/style_render.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2030,7 +2030,9 @@ def _class_styles(self):
20302030
}
20312031
]
20322032

2033-
def _pseudo_css(self, uuid: str, name: str, row: int, col: int, text: str):
2033+
def _pseudo_css(
2034+
self, uuid: str, name: str, row: int, col: int, text: str
2035+
) -> list[CSSDict]:
20342036
"""
20352037
For every table data-cell that has a valid tooltip (not None, NaN or
20362038
empty string) must create two pseudo CSS entries for the specific

pandas/io/html.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ def row_is_all_th(row):
469469

470470
def _expand_colspan_rowspan(
471471
self, rows, section: Literal["header", "footer", "body"]
472-
):
472+
) -> list[list]:
473473
"""
474474
Given a list of <tr>s, return a list of text rows.
475475

pandas/io/json/_normalize.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
TYPE_CHECKING,
1212
Any,
1313
DefaultDict,
14+
overload,
1415
)
1516

1617
import numpy as np
@@ -42,13 +43,35 @@ def convert_to_line_delimits(s: str) -> str:
4243
return convert_json_to_lines(s)
4344

4445

46+
@overload
4547
def nested_to_record(
46-
ds,
48+
ds: dict,
49+
prefix: str = ...,
50+
sep: str = ...,
51+
level: int = ...,
52+
max_level: int | None = ...,
53+
) -> dict[str, Any]:
54+
...
55+
56+
57+
@overload
58+
def nested_to_record(
59+
ds: list[dict],
60+
prefix: str = ...,
61+
sep: str = ...,
62+
level: int = ...,
63+
max_level: int | None = ...,
64+
) -> list[dict[str, Any]]:
65+
...
66+
67+
68+
def nested_to_record(
69+
ds: dict | list[dict],
4770
prefix: str = "",
4871
sep: str = ".",
4972
level: int = 0,
5073
max_level: int | None = None,
51-
):
74+
) -> dict[str, Any] | list[dict[str, Any]]:
5275
"""
5376
A simplified json_normalize
5477

pandas/io/parquet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def validate_dataframe(df: DataFrame) -> None:
150150
if not isinstance(df, DataFrame):
151151
raise ValueError("to_parquet only supports IO with DataFrames")
152152

153-
def write(self, df: DataFrame, path, compression, **kwargs):
153+
def write(self, df: DataFrame, path, compression, **kwargs) -> None:
154154
raise AbstractMethodError(self)
155155

156156
def read(self, path, columns=None, **kwargs) -> DataFrame:

pandas/io/parsers/base_parser.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@
8484

8585
if TYPE_CHECKING:
8686
from collections.abc import (
87-
Hashable,
8887
Iterable,
8988
Mapping,
9089
Sequence,
@@ -94,7 +93,10 @@
9493
ArrayLike,
9594
DtypeArg,
9695
DtypeObj,
96+
Hashable,
97+
HashableT,
9798
Scalar,
99+
SequenceT,
98100
)
99101

100102

@@ -350,13 +352,13 @@ def extract(r):
350352
@final
351353
def _maybe_make_multi_index_columns(
352354
self,
353-
columns: Sequence[Hashable],
355+
columns: SequenceT,
354356
col_names: Sequence[Hashable] | None = None,
355-
) -> Sequence[Hashable] | MultiIndex:
357+
) -> SequenceT | MultiIndex:
356358
# possibly create a column mi here
357359
if is_potential_multi_index(columns):
358-
list_columns = cast(list[tuple], columns)
359-
return MultiIndex.from_tuples(list_columns, names=col_names)
360+
columns_mi = cast("Sequence[tuple[Hashable, ...]]", columns)
361+
return MultiIndex.from_tuples(columns_mi, names=col_names)
360362
return columns
361363

362364
@final
@@ -520,7 +522,7 @@ def _convert_to_ndarrays(
520522
verbose: bool = False,
521523
converters=None,
522524
dtypes=None,
523-
):
525+
) -> dict[Any, np.ndarray]:
524526
result = {}
525527
for c, values in dct.items():
526528
conv_f = None if converters is None else converters.get(c, None)
@@ -923,23 +925,23 @@ def _check_data_length(
923925
@overload
924926
def _evaluate_usecols(
925927
self,
926-
usecols: set[int] | Callable[[Hashable], object],
927-
names: Sequence[Hashable],
928+
usecols: Callable[[Hashable], object],
929+
names: Iterable[Hashable],
928930
) -> set[int]:
929931
...
930932

931933
@overload
932934
def _evaluate_usecols(
933-
self, usecols: set[str], names: Sequence[Hashable]
934-
) -> set[str]:
935+
self, usecols: SequenceT, names: Iterable[Hashable]
936+
) -> SequenceT:
935937
...
936938

937939
@final
938940
def _evaluate_usecols(
939941
self,
940-
usecols: Callable[[Hashable], object] | set[str] | set[int],
941-
names: Sequence[Hashable],
942-
) -> set[str] | set[int]:
942+
usecols: Callable[[Hashable], object] | SequenceT,
943+
names: Iterable[Hashable],
944+
) -> SequenceT | set[int]:
943945
"""
944946
Check whether or not the 'usecols' parameter
945947
is a callable. If so, enumerates the 'names'
@@ -952,7 +954,7 @@ def _evaluate_usecols(
952954
return usecols
953955

954956
@final
955-
def _validate_usecols_names(self, usecols, names: Sequence):
957+
def _validate_usecols_names(self, usecols: SequenceT, names: Sequence) -> SequenceT:
956958
"""
957959
Validates that all usecols are present in a given
958960
list of names. If not, raise a ValueError that
@@ -1072,7 +1074,9 @@ def _clean_index_names(self, columns, index_col) -> tuple[list | None, list, lis
10721074
return index_names, columns, index_col
10731075

10741076
@final
1075-
def _get_empty_meta(self, columns, dtype: DtypeArg | None = None):
1077+
def _get_empty_meta(
1078+
self, columns: Sequence[HashableT], dtype: DtypeArg | None = None
1079+
) -> tuple[Index, list[HashableT], dict[HashableT, Series]]:
10761080
columns = list(columns)
10771081

10781082
index_col = self.index_col
@@ -1275,7 +1279,7 @@ def _process_date_conversion(
12751279
columns,
12761280
keep_date_col: bool = False,
12771281
dtype_backend=lib.no_default,
1278-
):
1282+
) -> tuple[dict, list]:
12791283
def _isindex(colspec):
12801284
return (isinstance(index_col, list) and colspec in index_col) or (
12811285
isinstance(index_names, list) and colspec in index_names

pandas/io/parsers/c_parser_wrapper.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@
4141
)
4242

4343
from pandas._typing import (
44+
AnyArrayLike,
4445
ArrayLike,
4546
DtypeArg,
4647
DtypeObj,
4748
ReadCsvBuffer,
49+
SequenceT,
4850
)
4951

5052
from pandas import (
@@ -225,7 +227,7 @@ def read(
225227
) -> tuple[
226228
Index | MultiIndex | None,
227229
Sequence[Hashable] | MultiIndex,
228-
Mapping[Hashable, ArrayLike],
230+
Mapping[Hashable, AnyArrayLike],
229231
]:
230232
index: Index | MultiIndex | None
231233
column_names: Sequence[Hashable] | MultiIndex
@@ -248,7 +250,11 @@ def read(
248250
names,
249251
dtype=self.dtype,
250252
)
251-
columns = self._maybe_make_multi_index_columns(columns, self.col_names)
253+
# error: Incompatible types in assignment (expression has type
254+
# "list[Hashable] | MultiIndex", variable has type "list[Hashable]")
255+
columns = self._maybe_make_multi_index_columns( # type: ignore[assignment]
256+
columns, self.col_names
257+
)
252258

253259
if self.usecols is not None:
254260
columns = self._filter_usecols(columns)
@@ -334,11 +340,11 @@ def read(
334340

335341
return index, column_names, date_data
336342

337-
def _filter_usecols(self, names: Sequence[Hashable]) -> Sequence[Hashable]:
343+
def _filter_usecols(self, names: SequenceT) -> SequenceT | list[Hashable]:
338344
# hackish
339345
usecols = self._evaluate_usecols(self.usecols, names)
340346
if usecols is not None and len(names) != len(usecols):
341-
names = [
347+
return [
342348
name for i, name in enumerate(names) if i in usecols or name in usecols
343349
]
344350
return names

pandas/io/parsers/python_parser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ def read(
266266
# done with first read, next time raise StopIteration
267267
self._first_chunk = False
268268

269+
index: Index | None
269270
columns: Sequence[Hashable] = list(self.orig_names)
270271
if not len(content): # pragma: no cover
271272
# DataFrame with the right metadata, even though it's length 0

pandas/io/parsers/readers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2101,7 +2101,7 @@ def _floatify_na_values(na_values):
21012101
return result
21022102

21032103

2104-
def _stringify_na_values(na_values, floatify: bool):
2104+
def _stringify_na_values(na_values, floatify: bool) -> set[str | float]:
21052105
"""return a stringified and numeric for these values"""
21062106
result: list[str | float] = []
21072107
for x in na_values:

pandas/io/sas/sas7bdat.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
from pandas._typing import (
5555
CompressionOptions,
5656
FilePath,
57+
NaTType,
5758
ReadBuffer,
5859
)
5960

@@ -62,7 +63,7 @@
6263
_sas_origin = Timestamp("1960-01-01")
6364

6465

65-
def _parse_datetime(sas_datetime: float, unit: str):
66+
def _parse_datetime(sas_datetime: float, unit: str) -> datetime | NaTType:
6667
if isna(sas_datetime):
6768
return pd.NaT
6869

@@ -326,7 +327,7 @@ def __next__(self) -> DataFrame:
326327
return da
327328

328329
# Read a single float of the given width (4 or 8).
329-
def _read_float(self, offset: int, width: int):
330+
def _read_float(self, offset: int, width: int) -> float:
330331
assert self._cached_page is not None
331332
if width == 4:
332333
return read_float_with_byteswap(

0 commit comments

Comments
 (0)