Skip to content

Commit 1c82694

Browse files
twoertweinjbrockmendelrhshadrachmroeschkeYulv-git
authored
TYP: Mypy workaround for NoDefault (#47045)
* TYP: NoDefault * ix mypy issues; re-write isinstance(..., NoDefault) * remove two more casts * ENH: DatetimeArray fields support non-nano (#47044) * DEPR: groupby numeric_only default (#47025) * DOC: Clarify decay argument validation in ewm when times is provided (#47026) * DOC: Fix some typos in pandas/. (#47022) * remove two more casts * avoid cast-like annotation * left/right * cannot use | Co-authored-by: jbrockmendel <[email protected]> Co-authored-by: Richard Shadrach <[email protected]> Co-authored-by: Matthew Roeschke <[email protected]> Co-authored-by: Shuangchi He <[email protected]>
1 parent c6886e2 commit 1c82694

File tree

15 files changed

+41
-52
lines changed

15 files changed

+41
-52
lines changed

pandas/_libs/lib.pyi

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ ndarray_obj_2d = np.ndarray
2323

2424
from enum import Enum
2525

26-
class NoDefault(Enum): ...
26+
class _NoDefault(Enum):
27+
no_default = ...
2728

28-
no_default: NoDefault
29+
no_default = _NoDefault.no_default
30+
NoDefault = Literal[_NoDefault.no_default]
2931

3032
i8max: int
3133
u8max: int

pandas/_libs/lib.pyx

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from collections import abc
22
from decimal import Decimal
33
from enum import Enum
4+
from typing import Literal
45
import warnings
56

67
cimport cython
@@ -2791,7 +2792,7 @@ cdef _infer_all_nats(dtype, ndarray datetimes, ndarray timedeltas):
27912792
return result
27922793

27932794

2794-
class NoDefault(Enum):
2795+
class _NoDefault(Enum):
27952796
# We make this an Enum
27962797
# 1) because it round-trips through pickle correctly (see GH#40397)
27972798
# 2) because mypy does not understand singletons
@@ -2802,7 +2803,8 @@ class NoDefault(Enum):
28022803

28032804

28042805
# Note: no_default is exported to the public API in pandas.api.extensions
2805-
no_default = NoDefault.no_default # Sentinel indicating the default value.
2806+
no_default = _NoDefault.no_default # Sentinel indicating the default value.
2807+
NoDefault = Literal[_NoDefault.no_default]
28062808

28072809

28082810
@cython.boundscheck(False)

pandas/_testing/asserters.py

+2-12
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,7 @@ def assert_almost_equal(
112112
FutureWarning,
113113
stacklevel=find_stack_level(),
114114
)
115-
# https://github.com/python/mypy/issues/7642
116-
# error: Argument 1 to "_get_tol_from_less_precise" has incompatible
117-
# type "Union[bool, int, NoDefault]"; expected "Union[bool, int]"
118-
rtol = atol = _get_tol_from_less_precise(
119-
check_less_precise # type: ignore[arg-type]
120-
)
115+
rtol = atol = _get_tol_from_less_precise(check_less_precise)
121116

122117
if isinstance(left, Index):
123118
assert_index_equal(
@@ -345,12 +340,7 @@ def _get_ilevel_values(index, level):
345340
FutureWarning,
346341
stacklevel=find_stack_level(),
347342
)
348-
# https://github.com/python/mypy/issues/7642
349-
# error: Argument 1 to "_get_tol_from_less_precise" has incompatible
350-
# type "Union[bool, int, NoDefault]"; expected "Union[bool, int]"
351-
rtol = atol = _get_tol_from_less_precise(
352-
check_less_precise # type: ignore[arg-type]
353-
)
343+
rtol = atol = _get_tol_from_less_precise(check_less_precise)
354344

355345
# instance validation
356346
_check_isinstance(left, right, Index)

pandas/_typing.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,8 @@ def closed(self) -> bool:
313313
XMLParsers = Literal["lxml", "etree"]
314314

315315
# Interval closed type
316-
IntervalClosedType = Literal["left", "right", "both", "neither"]
316+
IntervalLeftRight = Literal["left", "right"]
317+
IntervalClosedType = Union[IntervalLeftRight, Literal["both", "neither"]]
317318

318319
# datetime and NaTType
319320
DatetimeNaTType = Union[datetime, "NaTType"]

pandas/core/arrays/interval.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def _simple_new(
263263
cls: type[IntervalArrayT],
264264
left,
265265
right,
266-
closed=None,
266+
closed: IntervalClosedType | None = None,
267267
copy: bool = False,
268268
dtype: Dtype | None = None,
269269
verify_integrity: bool = True,
@@ -416,7 +416,7 @@ def _from_factorized(
416416
def from_breaks(
417417
cls: type[IntervalArrayT],
418418
breaks,
419-
closed="right",
419+
closed: IntervalClosedType | None = "right",
420420
copy: bool = False,
421421
dtype: Dtype | None = None,
422422
) -> IntervalArrayT:
@@ -492,7 +492,7 @@ def from_arrays(
492492
cls: type[IntervalArrayT],
493493
left,
494494
right,
495-
closed="right",
495+
closed: IntervalClosedType | None = "right",
496496
copy: bool = False,
497497
dtype: Dtype | None = None,
498498
) -> IntervalArrayT:
@@ -956,10 +956,10 @@ def _concat_same_type(
956956
-------
957957
IntervalArray
958958
"""
959-
closed = {interval.closed for interval in to_concat}
960-
if len(closed) != 1:
959+
closed_set = {interval.closed for interval in to_concat}
960+
if len(closed_set) != 1:
961961
raise ValueError("Intervals must all be closed on the same side.")
962-
closed = closed.pop()
962+
closed = closed_set.pop()
963963

964964
left = np.concatenate([interval.left for interval in to_concat])
965965
right = np.concatenate([interval.right for interval in to_concat])
@@ -1328,7 +1328,7 @@ def overlaps(self, other):
13281328
# ---------------------------------------------------------------------
13291329

13301330
@property
1331-
def closed(self):
1331+
def closed(self) -> IntervalClosedType:
13321332
"""
13331333
Whether the intervals are closed on the left-side, right-side, both or
13341334
neither.

pandas/core/common.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ def resolve_numeric_only(numeric_only: bool | None | lib.NoDefault) -> bool:
673673
# first default to None
674674
result = False
675675
else:
676-
result = cast(bool, numeric_only)
676+
result = numeric_only
677677
return result
678678

679679

pandas/core/frame.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -6279,8 +6279,7 @@ def dropna(
62796279
# faster equivalent to 'agg_obj.count(agg_axis) > 0'
62806280
mask = notna(agg_obj).any(axis=agg_axis, bool_only=False)
62816281
else:
6282-
if how is not no_default:
6283-
raise ValueError(f"invalid how option: {how}")
6282+
raise ValueError(f"invalid how option: {how}")
62846283

62856284
if np.all(mask):
62866285
result = self.copy()
@@ -8050,9 +8049,6 @@ def groupby(
80508049
raise TypeError("You have to supply one of 'by' and 'level'")
80518050
axis = self._get_axis_number(axis)
80528051

8053-
# https://github.com/python/mypy/issues/7642
8054-
# error: Argument "squeeze" to "DataFrameGroupBy" has incompatible type
8055-
# "Union[bool, NoDefault]"; expected "bool"
80568052
return DataFrameGroupBy(
80578053
obj=self,
80588054
keys=by,
@@ -8061,7 +8057,7 @@ def groupby(
80618057
as_index=as_index,
80628058
sort=sort,
80638059
group_keys=group_keys,
8064-
squeeze=squeeze, # type: ignore[arg-type]
8060+
squeeze=squeeze,
80658061
observed=observed,
80668062
dropna=dropna,
80678063
)

pandas/core/generic.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -7899,8 +7899,8 @@ def between_time(
78997899
FutureWarning,
79007900
stacklevel=find_stack_level(),
79017901
)
7902-
left = True if isinstance(include_start, lib.NoDefault) else include_start
7903-
right = True if isinstance(include_end, lib.NoDefault) else include_end
7902+
left = True if include_start is lib.no_default else include_start
7903+
right = True if include_end is lib.no_default else include_end
79047904

79057905
inc_dict: dict[tuple[bool_t, bool_t], IntervalClosedType] = {
79067906
(True, True): "both",
@@ -10690,7 +10690,6 @@ def _stat_function(
1069010690

1069110691
if axis is None:
1069210692
axis = self._stat_axis_number
10693-
axis = cast(Axis, axis)
1069410693
if level is not None:
1069510694
warnings.warn(
1069610695
"Using the level keyword in DataFrame and Series aggregations is "

pandas/core/groupby/generic.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1580,7 +1580,7 @@ def idxmax(
15801580
# DataFrame.idxmax for backwards compatibility
15811581
numeric_only_arg = None if axis == 0 else False
15821582
else:
1583-
numeric_only_arg = cast(bool, numeric_only)
1583+
numeric_only_arg = numeric_only
15841584

15851585
def func(df):
15861586
res = df._reduce(
@@ -1616,7 +1616,7 @@ def idxmin(
16161616
# DataFrame.idxmin for backwards compatibility
16171617
numeric_only_arg = None if axis == 0 else False
16181618
else:
1619-
numeric_only_arg = cast(bool, numeric_only)
1619+
numeric_only_arg = numeric_only
16201620

16211621
def func(df):
16221622
res = df._reduce(

pandas/core/groupby/groupby.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1277,9 +1277,7 @@ def _resolve_numeric_only(
12771277
else:
12781278
numeric_only = False
12791279

1280-
# error: Incompatible return value type (got "Union[bool, NoDefault]",
1281-
# expected "bool")
1282-
return numeric_only # type: ignore[return-value]
1280+
return numeric_only
12831281

12841282
def _maybe_warn_numeric_only_depr(
12851283
self, how: str, result: DataFrame | Series, numeric_only: bool | lib.NoDefault

pandas/core/indexes/datetimes.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
Dtype,
3535
DtypeObj,
3636
IntervalClosedType,
37+
IntervalLeftRight,
3738
npt,
3839
)
3940
from pandas.util._decorators import (
@@ -1039,12 +1040,12 @@ def date_range(
10391040
DatetimeIndex(['2017-01-02', '2017-01-03', '2017-01-04'],
10401041
dtype='datetime64[ns]', freq='D')
10411042
"""
1042-
if inclusive is not None and not isinstance(closed, lib.NoDefault):
1043+
if inclusive is not None and closed is not lib.no_default:
10431044
raise ValueError(
10441045
"Deprecated argument `closed` cannot be passed"
10451046
"if argument `inclusive` is not None"
10461047
)
1047-
elif not isinstance(closed, lib.NoDefault):
1048+
elif closed is not lib.no_default:
10481049
warnings.warn(
10491050
"Argument `closed` is deprecated in favor of `inclusive`.",
10501051
FutureWarning,
@@ -1087,7 +1088,7 @@ def bdate_range(
10871088
name: Hashable = None,
10881089
weekmask=None,
10891090
holidays=None,
1090-
closed: lib.NoDefault = lib.no_default,
1091+
closed: IntervalLeftRight | lib.NoDefault | None = lib.no_default,
10911092
inclusive: IntervalClosedType | None = None,
10921093
**kwargs,
10931094
) -> DatetimeIndex:

pandas/core/indexes/interval.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def __new__(
251251
def from_breaks(
252252
cls,
253253
breaks,
254-
closed: str = "right",
254+
closed: IntervalClosedType | None = "right",
255255
name: Hashable = None,
256256
copy: bool = False,
257257
dtype: Dtype | None = None,
@@ -282,7 +282,7 @@ def from_arrays(
282282
cls,
283283
left,
284284
right,
285-
closed: str = "right",
285+
closed: IntervalClosedType = "right",
286286
name: Hashable = None,
287287
copy: bool = False,
288288
dtype: Dtype | None = None,
@@ -957,7 +957,7 @@ def interval_range(
957957
periods=None,
958958
freq=None,
959959
name: Hashable = None,
960-
closed: lib.NoDefault = lib.no_default,
960+
closed: IntervalClosedType | lib.NoDefault = lib.no_default,
961961
inclusive: IntervalClosedType | None = None,
962962
) -> IntervalIndex:
963963
"""
@@ -1054,12 +1054,12 @@ def interval_range(
10541054
IntervalIndex([[1, 2], [2, 3], [3, 4], [4, 5]],
10551055
dtype='interval[int64, both]')
10561056
"""
1057-
if inclusive is not None and not isinstance(closed, lib.NoDefault):
1057+
if inclusive is not None and closed is not lib.no_default:
10581058
raise ValueError(
10591059
"Deprecated argument `closed` cannot be passed "
10601060
"if argument `inclusive` is not None"
10611061
)
1062-
elif not isinstance(closed, lib.NoDefault):
1062+
elif closed is not lib.no_default:
10631063
warnings.warn(
10641064
"Argument `closed` is deprecated in favor of `inclusive`.",
10651065
FutureWarning,

pandas/core/indexes/multi.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
Hashable,
1111
Iterable,
1212
List,
13+
Literal,
1314
Sequence,
1415
Tuple,
1516
cast,
@@ -1397,7 +1398,7 @@ def format(
13971398
sparsify = get_option("display.multi_sparse")
13981399

13991400
if sparsify:
1400-
sentinel = ""
1401+
sentinel: Literal[""] | bool | lib.NoDefault = ""
14011402
# GH3547 use value of sparsify as sentinel if it's "Falsey"
14021403
assert isinstance(sparsify, bool) or sparsify is lib.no_default
14031404
if sparsify in [False, lib.no_default]:

pandas/core/reshape/tile.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
Timestamp,
1717
)
1818
from pandas._libs.lib import infer_dtype
19+
from pandas._typing import IntervalLeftRight
1920

2021
from pandas.core.dtypes.common import (
2122
DT64NS_DTYPE,
@@ -560,7 +561,7 @@ def _format_labels(
560561
bins, precision: int, right: bool = True, include_lowest: bool = False, dtype=None
561562
):
562563
"""based on the dtype, return our labels"""
563-
closed = "right" if right else "left"
564+
closed: IntervalLeftRight = "right" if right else "left"
564565

565566
formatter: Callable[[Any], Timestamp] | Callable[[Any], Timedelta]
566567

pandas/core/series.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1952,8 +1952,6 @@ def groupby(
19521952
raise TypeError("You have to supply one of 'by' and 'level'")
19531953
axis = self._get_axis_number(axis)
19541954

1955-
# error: Argument "squeeze" to "SeriesGroupBy" has incompatible type
1956-
# "Union[bool, NoDefault]"; expected "bool"
19571955
return SeriesGroupBy(
19581956
obj=self,
19591957
keys=by,
@@ -1962,7 +1960,7 @@ def groupby(
19621960
as_index=as_index,
19631961
sort=sort,
19641962
group_keys=group_keys,
1965-
squeeze=squeeze, # type: ignore[arg-type]
1963+
squeeze=squeeze,
19661964
observed=observed,
19671965
dropna=dropna,
19681966
)

0 commit comments

Comments
 (0)