From 46fb50293e74cec8b54d13e40bdf2266720c9e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20V=C3=A1zquez=20Acosta?= Date: Tue, 20 Sep 2022 16:54:35 +0200 Subject: [PATCH] Make JSONEncoder keep the same type for date/datetime. Otherwise Celery jobs start to get `datetime` in place of `date` and that could lead to errors. See https://github.com/celery/celery/issues/7754, related PR #1515. --- AUTHORS | 1 + kombu/utils/json.py | 7 ++++++- t/unit/utils/test_json.py | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index d1664a3f8..155cd5d06 100644 --- a/AUTHORS +++ b/AUTHORS @@ -89,6 +89,7 @@ Lorenzo Mancini Luyun Xie <2304310@qq.com> Mads Jensen Mahendra M +Manuel Vazquez Acosta Marcin Lulek (ergo) Marcin Puhacz Mark Lavin diff --git a/kombu/utils/json.py b/kombu/utils/json.py index a5a020c18..95a05a680 100644 --- a/kombu/utils/json.py +++ b/kombu/utils/json.py @@ -38,10 +38,13 @@ def default(self, o, return reducer() else: if isinstance(o, dates): + marker = "__date__" if not isinstance(o, datetime): o = datetime(o.year, o.month, o.day, 0, 0, 0, 0) + else: + marker = "__datetime__" r = o.isoformat() - return {"datetime": r, "__datetime__": True} + return {"datetime": r, marker: True} elif isinstance(o, times): return o.isoformat() elif isinstance(o, uuid.UUID): @@ -71,6 +74,8 @@ def dumps(s, _dumps=json.dumps, cls=None, default_kwargs=None, **kwargs): def object_hook(dct): """Hook function to perform custom deserialization.""" + if "__date__" in dct: + return datetime.datetime.fromisoformat(dct["datetime"]).date() if "__datetime__" in dct: return datetime.datetime.fromisoformat(dct["datetime"]) if "__bytes__" in dct: diff --git a/t/unit/utils/test_json.py b/t/unit/utils/test_json.py index 0f1f02b23..ec7ea1023 100644 --- a/t/unit/utils/test_json.py +++ b/t/unit/utils/test_json.py @@ -2,7 +2,7 @@ import uuid from collections import namedtuple -from datetime import datetime +from datetime import date, datetime from decimal import Decimal from unittest.mock import MagicMock, Mock @@ -39,7 +39,7 @@ def test_datetime(self): 'datetime': now, 'tz': now_utc, 'time': now.time().isoformat(), - 'date': datetime(now.year, now.month, now.day, 0, 0, 0, 0), + 'date': date(now.year, now.month, now.day), } @given(message=st.binary())