From 5e3bd35ea4ab4bdc5d03aef3515f6293458d428a Mon Sep 17 00:00:00 2001 From: Alexander Lukanin Date: Tue, 24 Mar 2026 16:05:20 +0600 Subject: [PATCH] fix: pendulum.parse('2007-12-13/14:30') raised TypeError instead of uniform ValueError Time object was falling through type checks in Interval.__new__ --- src/pendulum/interval.py | 5 +++-- tests/test_parsing.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/pendulum/interval.py b/src/pendulum/interval.py index c5e0713a..c35cd6af 100644 --- a/src/pendulum/interval.py +++ b/src/pendulum/interval.py @@ -39,8 +39,9 @@ class Interval(Duration, Generic[_T]): """ def __new__(cls, start: _T, end: _T, absolute: bool = False) -> Self: - if (isinstance(start, datetime) and not isinstance(end, datetime)) or ( - not isinstance(start, datetime) and isinstance(end, datetime) + if (isinstance(start, datetime) and not isinstance(end, datetime) or + not isinstance(start, datetime) and isinstance(end, datetime) or + not (isinstance(start, date) and isinstance(end, date)) # Time not allowed ): raise ValueError( "Both start and end of an Interval must have the same type" diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 34673c40..4f7eb2ef 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -1,5 +1,7 @@ from __future__ import annotations +import pytest + import pendulum from tests.conftest import assert_date @@ -127,6 +129,19 @@ def test_parse_interval() -> None: assert interval.end.offset == 0 +def test_parse_interval_mixed_types(): + error = 'Both start and end of an Interval must have the same type' + + # date / time is not allowed in ISO 8601 + with pytest.raises(ValueError, match=error): + pendulum.parse('2007-12-13/14:30') + + # datetime / time is allowed in some lenient ISO 8601 implementations (e.g. aniso8601 package). + # Not allowed in pendulum for strictness and consistency. + with pytest.raises(ValueError, match=error): + pendulum.parse('2007-12-13T14:30/15:45') + + def test_parse_now() -> None: assert pendulum.parse("now").timezone_name == "UTC" assert (