Skip to content

Commit 1896191

Browse files
Use the new TypeIs feature to update the notna/notnull/isna/isnull type guards (#972)
* GH 927 Allow 'integer' in select_dtypes include argument * TypeGuard clean up in dtypes/missing.pyi * PR Feedback
1 parent 1b4fd6f commit 1896191

File tree

2 files changed

+12
-34
lines changed

2 files changed

+12
-34
lines changed

pandas-stubs/core/dtypes/missing.pyi

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ from pandas import (
1010
Index,
1111
Series,
1212
)
13-
from typing_extensions import TypeGuard
13+
from typing_extensions import TypeIs
1414

1515
from pandas._libs.missing import NAType
1616
from pandas._libs.tslibs import NaTType
@@ -32,7 +32,7 @@ def isna(obj: Index[Any] | list[Any] | ArrayLike) -> npt.NDArray[np.bool_]: ...
3232
@overload
3333
def isna(
3434
obj: Scalar | NaTType | NAType | None,
35-
) -> TypeGuard[NaTType | NAType | None]: ...
35+
) -> TypeIs[NaTType | NAType | None]: ...
3636

3737
isnull = isna
3838

@@ -43,6 +43,6 @@ def notna(obj: Series[Any]) -> Series[bool]: ...
4343
@overload
4444
def notna(obj: Index[Any] | list[Any] | ArrayLike) -> npt.NDArray[np.bool_]: ...
4545
@overload
46-
def notna(obj: ScalarT | NaTType | NAType | None) -> TypeGuard[ScalarT]: ...
46+
def notna(obj: ScalarT | NaTType | NAType | None) -> TypeIs[ScalarT]: ...
4747

4848
notnull = notna

tests/test_pandas.py

+9-31
Original file line numberDiff line numberDiff line change
@@ -366,60 +366,38 @@ def test_isna() -> None:
366366
assert check(assert_type(pd.isna(np_nat), bool), bool)
367367
assert not check(assert_type(pd.notna(np_nat), bool), bool)
368368

369-
# Check TypeGuard type narrowing functionality
370-
# TODO: Due to limitations in TypeGuard spec, the true annotations are not always viable
371-
# and as a result the type narrowing does not always work as it intuitively should
372-
# There is a proposal being floated for a StrictTypeGuard that will have more rigid narrowing semantics
373-
# In the test cases below, a commented out assertion will be included to document the optimal test result
369+
# Check TypeIs type narrowing functionality
374370
nullable1: str | None | NAType | NaTType = random.choice(
375371
["value", None, pd.NA, pd.NaT]
376372
)
377373
if pd.notna(nullable1):
378374
check(assert_type(nullable1, str), str)
379375
if not pd.isna(nullable1):
380-
# check(assert_type(nullable1, str), str) # TODO: Desired result (see comments above)
381-
check(assert_type(nullable1, Union[str, NaTType, NAType, None]), str)
376+
check(assert_type(nullable1, str), str)
382377
if pd.isna(nullable1):
383378
assert_type(nullable1, Union[NaTType, NAType, None])
384379
if not pd.notna(nullable1):
385-
# assert_type(nullable1, Union[NaTType, NAType, None]) # TODO: Desired result (see comments above)
386-
assert_type(nullable1, Union[str, NaTType, NAType, None])
380+
assert_type(nullable1, Union[NaTType, NAType, None])
387381

388382
nullable2: int | None = random.choice([2, None])
389383
if pd.notna(nullable2):
390384
check(assert_type(nullable2, int), int)
391385
if not pd.isna(nullable2):
392-
# check(assert_type(nullable2, int), int) # TODO: Desired result (see comments above)
393-
check(assert_type(nullable2, Union[int, None]), int)
386+
check(assert_type(nullable2, int), int)
394387
if pd.isna(nullable2):
395-
# check(assert_type(nullable2, None), type(None)) # TODO: Desired result (see comments above)
396-
check(assert_type(nullable2, Union[NaTType, NAType, None]), type(None))
388+
check(assert_type(nullable2, None), type(None))
397389
if not pd.notna(nullable2):
398-
# check(assert_type(nullable2, None), type(None)) # TODO: Desired result (see comments above)
399-
# TODO: MyPy and Pyright produce conflicting results:
400-
# assert_type(nullable2, Union[int, None]) # MyPy result
401-
# assert_type(
402-
# nullable2, Union[int, NaTType, NAType, None]
403-
# ) # Pyright result
404-
pass
390+
check(assert_type(nullable2, None), type(None))
405391

406392
nullable3: bool | None | NAType = random.choice([True, None, pd.NA])
407393
if pd.notna(nullable3):
408394
check(assert_type(nullable3, bool), bool)
409395
if not pd.isna(nullable3):
410-
# check(assert_type(nullable3, bool), bool) # TODO: Desired result (see comments above)
411-
check(assert_type(nullable3, Union[bool, NAType, None]), bool)
396+
check(assert_type(nullable3, bool), bool)
412397
if pd.isna(nullable3):
413-
# assert_type(nullable3, Union[NAType, None]) # TODO: Desired result (see comments above)
414-
assert_type(nullable3, Union[NaTType, NAType, None])
398+
assert_type(nullable3, Union[NAType, None])
415399
if not pd.notna(nullable3):
416-
# assert_type(nullable3, Union[NAType, None]) # TODO: Desired result (see comments above)
417-
# TODO: MyPy and Pyright produce conflicting results:
418-
# assert_type(nullable3, Union[bool, NAType, None]) # Mypy result
419-
# assert_type(
420-
# nullable3, Union[bool, NaTType, NAType, None]
421-
# ) # Pyright result
422-
pass
400+
assert_type(nullable3, Union[NAType, None])
423401

424402

425403
# GH 55

0 commit comments

Comments
 (0)