From ca032f7207904a741440e6ba8e238bcf564d53cb Mon Sep 17 00:00:00 2001 From: Anton Petnitsky <168552591+Mukller@users.noreply.github.com> Date: Thu, 30 Jul 2026 18:52:46 +0300 Subject: [PATCH 1/2] fix: skip __round__ for datetime keys in number_to_string (fixes #550) datetimes is included in the `numbers` tuple so that datetime objects can be passed to number_to_string(). However, the `else` branch calls round(number, ndigits=significant_digits) which raises: TypeError: type datetime.datetime doesn't define __round__ method Add an `elif isinstance(number, datetimes): return number` branch before `else` so that datetime/date/timedelta/time values exit early, unchanged. This matches the intention: these types are already hashable and unique and need no numeric rounding for key-comparison purposes. --- deepdiff/helper.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/deepdiff/helper.py b/deepdiff/helper.py index 3fc61183..682c6571 100644 --- a/deepdiff/helper.py +++ b/deepdiff/helper.py @@ -510,6 +510,11 @@ def number_to_string(number: Any, significant_digits: int, number_format_notatio ) ) # type: ignore ) + elif isinstance(number, datetimes): + # datetime/date/timedelta/time objects are used as dict keys but do not + # support __round__. They are already unique enough for comparison, so + # return them unchanged (no string formatting needed for key identity). + return number else: number = round(number=number, ndigits=significant_digits) # type: ignore From fc24b97c76a684d82878249c12838b21d51dc93b Mon Sep 17 00:00:00 2001 From: Anton Petnitsky <168552591+Mukller@users.noreply.github.com> Date: Thu, 30 Jul 2026 18:53:18 +0300 Subject: [PATCH 2/2] test: regression for #550 (datetime dict key with ignore_numeric_type_changes) Add test_number_to_string_with_datetime_key and test_deepdiff_with_datetime_key_and_ignore_numeric to verify that datetime/date/timedelta/time objects do not raise TypeError when passed to number_to_string() with significant_digits set. --- tests/test_helper.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/test_helper.py b/tests/test_helper.py index 30942efe..ca187beb 100644 --- a/tests/test_helper.py +++ b/tests/test_helper.py @@ -198,6 +198,35 @@ def test_number_to_string_with_invalid_notation(self): with pytest.raises(ValueError): number_to_string(10, significant_digits=4, number_format_notation='blah') + + + def test_number_to_string_with_datetime_key(self): + """Regression for #550: datetime used as dict key must not raise TypeError. + + number_to_string() includes datetimes in the `numbers` tuple for + comparison purposes, but datetime objects don't implement __round__. + The fix adds an early-return branch for datetimes so they pass + through unchanged without reaching round(). + """ + import datetime + dt = datetime.datetime(2020, 5, 17, 22, 15) + date = datetime.date(2020, 5, 17) + td = datetime.timedelta(hours=1) + t = datetime.time(22, 15) + # None of these should raise + assert number_to_string(dt, significant_digits=5) == dt + assert number_to_string(date, significant_digits=5) == date + assert number_to_string(td, significant_digits=5) == td + assert number_to_string(t, significant_digits=5) == t + + def test_deepdiff_with_datetime_key_and_ignore_numeric(self): + """Integration: DeepDiff with datetime key and ignore_numeric_type_changes=True (#550).""" + import datetime + from deepdiff import DeepDiff + d1 = {datetime.datetime(2020, 5, 17, 22, 15): 10.0} + d2 = {datetime.datetime(2020, 5, 17, 22, 15): 10} + diff = DeepDiff(d1, d2, ignore_numeric_type_changes=True) + assert diff == {}, f"Expected empty diff, got: {diff}" def test_cartesian_product_of_shape(self): result = list(cartesian_product_of_shape([2, 1, 3])) assert [(0, 0, 0), (0, 0, 1), (0, 0, 2), (1, 0, 0), (1, 0, 1), (1, 0, 2)] == result