|
5 | 5 | from typing import (
|
6 | 6 | TYPE_CHECKING,
|
7 | 7 | Any,
|
8 |
| - Literal, |
9 | 8 | Union,
|
10 | 9 | )
|
11 | 10 |
|
|
17 | 16 | import pytest
|
18 | 17 | from typing_extensions import assert_type
|
19 | 18 |
|
| 19 | +from pandas._libs.missing import NAType |
| 20 | +from pandas._libs.tslibs import NaTType |
20 | 21 | from pandas._typing import Scalar
|
21 | 22 |
|
22 | 23 | from tests import (
|
@@ -246,17 +247,72 @@ def test_isna() -> None:
|
246 | 247 | idx2 = pd.Index([1, 2])
|
247 | 248 | check(assert_type(pd.notna(idx2), npt.NDArray[np.bool_]), np.ndarray, np.bool_)
|
248 | 249 |
|
249 |
| - assert check(assert_type(pd.isna(pd.NA), Literal[True]), bool) |
250 |
| - assert not check(assert_type(pd.notna(pd.NA), Literal[False]), bool) |
251 |
| - |
252 |
| - assert check(assert_type(pd.isna(pd.NaT), Literal[True]), bool) |
253 |
| - assert not check(assert_type(pd.notna(pd.NaT), Literal[False]), bool) |
254 |
| - |
255 |
| - assert check(assert_type(pd.isna(None), Literal[True]), bool) |
256 |
| - assert not check(assert_type(pd.notna(None), Literal[False]), bool) |
257 |
| - |
258 |
| - check(assert_type(pd.isna(2.5), bool), bool) |
259 |
| - check(assert_type(pd.notna(2.5), bool), bool) |
| 250 | + assert check(assert_type(pd.isna(pd.NA), bool), bool) |
| 251 | + assert not check(assert_type(pd.notna(pd.NA), bool), bool) |
| 252 | + |
| 253 | + assert check(assert_type(pd.isna(pd.NaT), bool), bool) |
| 254 | + assert not check(assert_type(pd.notna(pd.NaT), bool), bool) |
| 255 | + |
| 256 | + assert check(assert_type(pd.isna(None), bool), bool) |
| 257 | + assert not check(assert_type(pd.notna(None), bool), bool) |
| 258 | + |
| 259 | + assert not check(assert_type(pd.isna(2.5), bool), bool) |
| 260 | + assert check(assert_type(pd.notna(2.5), bool), bool) |
| 261 | + |
| 262 | + # Check TypeGuard type narrowing functionality |
| 263 | + # TODO: Due to limitations in TypeGuard spec, the true annotations are not always viable |
| 264 | + # and as a result the type narrowing does not always work as it intuitively should |
| 265 | + # There is a proposal being floated for a StrictTypeGuard that will have more rigid narrowing semantics |
| 266 | + # In the test cases below, a commented out assertion will be included to document the optimal test result |
| 267 | + nullable1: str | None | NAType | NaTType = random.choice( |
| 268 | + ["value", None, pd.NA, pd.NaT] |
| 269 | + ) |
| 270 | + if pd.notna(nullable1): |
| 271 | + check(assert_type(nullable1, str), str) |
| 272 | + if not pd.isna(nullable1): |
| 273 | + # check(assert_type(nullable1, str), str) # TODO: Desired result (see comments above) |
| 274 | + check(assert_type(nullable1, Union[str, NaTType, NAType, None]), str) |
| 275 | + if pd.isna(nullable1): |
| 276 | + assert_type(nullable1, Union[NaTType, NAType, None]) |
| 277 | + if not pd.notna(nullable1): |
| 278 | + # assert_type(nullable1, Union[NaTType, NAType, None]) # TODO: Desired result (see comments above) |
| 279 | + assert_type(nullable1, Union[str, NaTType, NAType, None]) |
| 280 | + |
| 281 | + nullable2: int | None = random.choice([2, None]) |
| 282 | + if pd.notna(nullable2): |
| 283 | + check(assert_type(nullable2, int), int) |
| 284 | + if not pd.isna(nullable2): |
| 285 | + # check(assert_type(nullable2, int), int) # TODO: Desired result (see comments above) |
| 286 | + check(assert_type(nullable2, Union[int, None]), int) |
| 287 | + if pd.isna(nullable2): |
| 288 | + # check(assert_type(nullable2, None), type(None)) # TODO: Desired result (see comments above) |
| 289 | + check(assert_type(nullable2, Union[NaTType, NAType, None]), type(None)) |
| 290 | + if not pd.notna(nullable2): |
| 291 | + # check(assert_type(nullable2, None), type(None)) # TODO: Desired result (see comments above) |
| 292 | + # TODO: MyPy and Pyright produce conflicting results: |
| 293 | + # assert_type(nullable2, Union[int, None]) # MyPy result |
| 294 | + # assert_type( |
| 295 | + # nullable2, Union[int, NaTType, NAType, None] |
| 296 | + # ) # Pyright result |
| 297 | + pass |
| 298 | + |
| 299 | + nullable3: bool | None | NAType = random.choice([True, None, pd.NA]) |
| 300 | + if pd.notna(nullable3): |
| 301 | + check(assert_type(nullable3, bool), bool) |
| 302 | + if not pd.isna(nullable3): |
| 303 | + # check(assert_type(nullable3, bool), bool) # TODO: Desired result (see comments above) |
| 304 | + check(assert_type(nullable3, Union[bool, NAType, None]), bool) |
| 305 | + if pd.isna(nullable3): |
| 306 | + # assert_type(nullable3, Union[NAType, None]) # TODO: Desired result (see comments above) |
| 307 | + assert_type(nullable3, Union[NaTType, NAType, None]) |
| 308 | + if not pd.notna(nullable3): |
| 309 | + # assert_type(nullable3, Union[NAType, None]) # TODO: Desired result (see comments above) |
| 310 | + # TODO: MyPy and Pyright produce conflicting results: |
| 311 | + # assert_type(nullable3, Union[bool, NAType, None]) # Mypy result |
| 312 | + # assert_type( |
| 313 | + # nullable3, Union[bool, NaTType, NAType, None] |
| 314 | + # ) # Pyright result |
| 315 | + pass |
260 | 316 |
|
261 | 317 |
|
262 | 318 | # GH 55
|
|
0 commit comments