From 3ea22c9d94736d799c8f3a906a0c46a25c25ccdc Mon Sep 17 00:00:00 2001 From: Aniket Singh Yadav Date: Mon, 20 Apr 2026 16:41:42 +0000 Subject: [PATCH 1/4] add type tests covering all relevant datetime64 and timedelta64 --- .../static/accept/temporal_scalar_ops.pyi | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi diff --git a/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi b/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi new file mode 100644 index 00000000..ed8f07b3 --- /dev/null +++ b/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi @@ -0,0 +1,72 @@ +# Type tests for datetime64/timedelta64 operations using representative subtype cases + +import datetime as dt +from typing import assert_type + +import numpy as np + +DT = np.datetime64 +TD = np.timedelta64 + +dt_default: DT +dt_none: DT[None] +dt_int: DT[int] +dt_datetime: DT[dt.datetime] +dt_date: DT[dt.date] + +td_default: TD +td_none: TD[None] +td_int: TD[int] +td_timedelta: TD[dt.timedelta] + +assert_type(dt_default + td_default, DT) +assert_type(dt_default + td_none, DT[None]) +assert_type(dt_none + td_default, DT[None]) +assert_type(dt_int + td_int, DT[int]) +assert_type(dt_datetime + td_timedelta, DT[dt.datetime]) +assert_type(dt_date + td_timedelta, DT[dt.date]) + +assert_type(dt_default - td_default, DT) +assert_type(dt_default - td_none, DT[None]) +assert_type(dt_none - td_default, DT[None]) +assert_type(dt_int - td_int, DT[int]) +assert_type(dt_datetime - td_timedelta, DT[dt.datetime]) +assert_type(dt_date - td_timedelta, DT[dt.date]) +assert_type(dt_date - td_int, DT[dt.date | int]) + +assert_type(dt_default - dt_default, TD) +assert_type(dt_none - dt_default, TD[None]) +assert_type(dt_int - dt_int, TD[int]) +assert_type(dt_datetime - dt_datetime, TD[dt.timedelta]) +assert_type(dt_date - dt_date, TD[dt.timedelta]) + +assert_type(td_default + td_default, TD) +assert_type(td_none + td_default, TD[None]) +assert_type(td_int + td_int, TD[int]) +assert_type(td_timedelta + td_timedelta, TD[dt.timedelta]) + +assert_type(td_default - td_default, TD) +assert_type(td_none - td_default, TD[None]) +assert_type(td_int - td_int, TD[int]) +assert_type(td_timedelta - td_timedelta, TD[dt.timedelta]) + +assert_type(td_default / td_default, np.float64) +assert_type(td_none / td_default, np.float64) + +assert_type(td_default % td_default, TD) +assert_type(td_none % td_default, TD[None]) + +assert_type(td_default * 0, TD) +assert_type(td_none * 0, TD[None]) +assert_type(td_int * 0, TD[int]) +assert_type(td_timedelta * 0, TD[dt.timedelta]) + +assert_type(0 * td_default, TD) +assert_type(0 * td_none, TD[None]) +assert_type(0 * td_int, TD[int]) +assert_type(0 * td_timedelta, TD[dt.timedelta]) + +assert_type(td_default / 0, TD) +assert_type(td_none / 0, TD[None]) +assert_type(td_int / 0, TD[int]) +assert_type(td_timedelta / 0, TD[dt.timedelta]) From f7453feb2e4c20c8fb287fa43e8ef09b97b65887 Mon Sep 17 00:00:00 2001 From: Aniket Singh Yadav Date: Mon, 20 Apr 2026 19:04:26 +0000 Subject: [PATCH 2/4] tests: ignore assert_type errors --- .../@test/static/accept/temporal_scalar_ops.pyi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi b/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi index ed8f07b3..1de4ed13 100644 --- a/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi +++ b/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi @@ -21,32 +21,32 @@ td_timedelta: TD[dt.timedelta] assert_type(dt_default + td_default, DT) assert_type(dt_default + td_none, DT[None]) -assert_type(dt_none + td_default, DT[None]) +assert_type(dt_none + td_default, DT[None]) # type: ignore[assert-type] assert_type(dt_int + td_int, DT[int]) assert_type(dt_datetime + td_timedelta, DT[dt.datetime]) assert_type(dt_date + td_timedelta, DT[dt.date]) assert_type(dt_default - td_default, DT) assert_type(dt_default - td_none, DT[None]) -assert_type(dt_none - td_default, DT[None]) +assert_type(dt_none - td_default, DT[None]) # type: ignore[assert-type] assert_type(dt_int - td_int, DT[int]) assert_type(dt_datetime - td_timedelta, DT[dt.datetime]) assert_type(dt_date - td_timedelta, DT[dt.date]) assert_type(dt_date - td_int, DT[dt.date | int]) assert_type(dt_default - dt_default, TD) -assert_type(dt_none - dt_default, TD[None]) +assert_type(dt_none - dt_default, TD[None]) # type: ignore[assert-type] assert_type(dt_int - dt_int, TD[int]) assert_type(dt_datetime - dt_datetime, TD[dt.timedelta]) assert_type(dt_date - dt_date, TD[dt.timedelta]) assert_type(td_default + td_default, TD) -assert_type(td_none + td_default, TD[None]) +assert_type(td_none + td_default, TD[None]) # type: ignore[assert-type] assert_type(td_int + td_int, TD[int]) assert_type(td_timedelta + td_timedelta, TD[dt.timedelta]) assert_type(td_default - td_default, TD) -assert_type(td_none - td_default, TD[None]) +assert_type(td_none - td_default, TD[None]) # type: ignore[assert-type] assert_type(td_int - td_int, TD[int]) assert_type(td_timedelta - td_timedelta, TD[dt.timedelta]) @@ -54,7 +54,7 @@ assert_type(td_default / td_default, np.float64) assert_type(td_none / td_default, np.float64) assert_type(td_default % td_default, TD) -assert_type(td_none % td_default, TD[None]) +assert_type(td_none % td_default, TD[None]) # type: ignore[assert-type] assert_type(td_default * 0, TD) assert_type(td_none * 0, TD[None]) From 04b68e7897e98e911e6ce4da19fa435c482fd150 Mon Sep 17 00:00:00 2001 From: Aniket Singh Yadav Date: Tue, 21 Apr 2026 11:04:08 +0000 Subject: [PATCH 3/4] add comment for type ignores --- src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi b/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi index 1de4ed13..7cdb961b 100644 --- a/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi +++ b/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi @@ -21,6 +21,7 @@ td_timedelta: TD[dt.timedelta] assert_type(dt_default + td_default, DT) assert_type(dt_default + td_none, DT[None]) +# mypy produces datetime64[Any] instead of datetime64[None] for datetime64[None] operands. assert_type(dt_none + td_default, DT[None]) # type: ignore[assert-type] assert_type(dt_int + td_int, DT[int]) assert_type(dt_datetime + td_timedelta, DT[dt.datetime]) From cca2596c3e65c08d3df4d7484a68993622713a37 Mon Sep 17 00:00:00 2001 From: Aniket <148300120+Aniketsy@users.noreply.github.com> Date: Tue, 21 Apr 2026 17:28:15 +0530 Subject: [PATCH 4/4] Update src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi --- src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi b/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi index 7cdb961b..020971dc 100644 --- a/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi +++ b/src/numpy-stubs/@test/static/accept/temporal_scalar_ops.pyi @@ -21,7 +21,7 @@ td_timedelta: TD[dt.timedelta] assert_type(dt_default + td_default, DT) assert_type(dt_default + td_none, DT[None]) -# mypy produces datetime64[Any] instead of datetime64[None] for datetime64[None] operands. +# mypy incorrectly infers this as "timedelta64[Any]" but pyright behaves correctly assert_type(dt_none + td_default, DT[None]) # type: ignore[assert-type] assert_type(dt_int + td_int, DT[int]) assert_type(dt_datetime + td_timedelta, DT[dt.datetime])