Skip to content

Commit 64a569c

Browse files
authored
fix(jsonapi_serializer): allow date, datetime and time for both of theses types (#329)
1 parent e87b6f6 commit 64a569c

File tree

2 files changed

+141
-4
lines changed

2 files changed

+141
-4
lines changed

src/agent_toolkit/forestadmin/agent_toolkit/services/serializers/json_api_serializer.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from ast import literal_eval
2-
from datetime import date, datetime, time
32
from typing import Any, Callable, Dict, List, Optional, Tuple, Union, cast
43
from urllib.parse import quote
54
from uuid import uuid4
@@ -134,15 +133,18 @@ def number_dump(val):
134133
elif isinstance(val, str):
135134
return literal_eval(str(value))
136135

136+
def date_types_dump(val):
137+
return val if isinstance(val, str) else val.isoformat()
138+
137139
parser_map: Dict[PrimitiveType, Callable] = {
138140
PrimitiveType.STRING: str,
139141
PrimitiveType.ENUM: str,
140142
PrimitiveType.BOOLEAN: bool,
141143
PrimitiveType.NUMBER: number_dump,
142144
PrimitiveType.UUID: str,
143-
PrimitiveType.DATE_ONLY: lambda v: v if isinstance(v, str) else date.isoformat(v),
144-
PrimitiveType.TIME_ONLY: lambda v: v if isinstance(v, str) else time.isoformat(v),
145-
PrimitiveType.DATE: lambda v: v if isinstance(v, str) else datetime.isoformat(v),
145+
PrimitiveType.DATE_ONLY: date_types_dump,
146+
PrimitiveType.TIME_ONLY: date_types_dump,
147+
PrimitiveType.DATE: date_types_dump,
146148
PrimitiveType.POINT: lambda v: v,
147149
PrimitiveType.BINARY: lambda v: v, # should not be called, because of binary decorator this type
148150
# is transformed to string

src/agent_toolkit/tests/services/serializers/test_jsonapi.py

+135
Original file line numberDiff line numberDiff line change
@@ -1371,3 +1371,138 @@ def test_string_foreign_keys_should_be_url_encoded_so_foreign_pk(self):
13711371
],
13721372
},
13731373
)
1374+
1375+
def test_datetime_should_also_serialize_dates_and_times(self):
1376+
serializer = JsonApiSerializer(self.datasource, Projection("all_types_pk", "datetime"))
1377+
record = {
1378+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1379+
"datetime": date(2023, 10, 10),
1380+
}
1381+
# date
1382+
dumped = serializer.serialize(record, self.collection_all_types)
1383+
self.assertEqual(
1384+
dumped,
1385+
{
1386+
"data": {
1387+
"type": "AllTypes",
1388+
"id": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1389+
"attributes": {
1390+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1391+
"datetime": "2023-10-10",
1392+
},
1393+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1394+
},
1395+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1396+
},
1397+
)
1398+
# time
1399+
record = {
1400+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1401+
"datetime": time(12, 12, 12),
1402+
}
1403+
dumped = serializer.serialize(record, self.collection_all_types)
1404+
self.assertEqual(
1405+
dumped,
1406+
{
1407+
"data": {
1408+
"type": "AllTypes",
1409+
"id": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1410+
"attributes": {
1411+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1412+
"datetime": "12:12:12",
1413+
},
1414+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1415+
},
1416+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1417+
},
1418+
)
1419+
1420+
def test_date_should_also_serialize_datetimes_and_times(self):
1421+
serializer = JsonApiSerializer(self.datasource, Projection("all_types_pk", "dateonly"))
1422+
record = {
1423+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1424+
"dateonly": datetime(2023, 10, 10, 12, 12, 12),
1425+
}
1426+
# datetime
1427+
dumped = serializer.serialize(record, self.collection_all_types)
1428+
self.assertEqual(
1429+
dumped,
1430+
{
1431+
"data": {
1432+
"type": "AllTypes",
1433+
"id": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1434+
"attributes": {
1435+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1436+
"dateonly": "2023-10-10T12:12:12",
1437+
},
1438+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1439+
},
1440+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1441+
},
1442+
)
1443+
# time
1444+
record = {
1445+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1446+
"dateonly": time(12, 12, 12),
1447+
}
1448+
dumped = serializer.serialize(record, self.collection_all_types)
1449+
self.assertEqual(
1450+
dumped,
1451+
{
1452+
"data": {
1453+
"type": "AllTypes",
1454+
"id": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1455+
"attributes": {
1456+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1457+
"dateonly": "12:12:12",
1458+
},
1459+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1460+
},
1461+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1462+
},
1463+
)
1464+
1465+
def test_time_only_should_also_serialize_dates_and_datetimes(self):
1466+
serializer = JsonApiSerializer(self.datasource, Projection("all_types_pk", "time_only"))
1467+
record = {
1468+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1469+
"time_only": datetime(2023, 10, 10, 12, 12, 12),
1470+
}
1471+
# datetime
1472+
dumped = serializer.serialize(record, self.collection_all_types)
1473+
self.assertEqual(
1474+
dumped,
1475+
{
1476+
"data": {
1477+
"type": "AllTypes",
1478+
"id": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1479+
"attributes": {
1480+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1481+
"time_only": "2023-10-10T12:12:12",
1482+
},
1483+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1484+
},
1485+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1486+
},
1487+
)
1488+
# date
1489+
record = {
1490+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1491+
"time_only": date(2023, 10, 10),
1492+
}
1493+
dumped = serializer.serialize(record, self.collection_all_types)
1494+
self.assertEqual(
1495+
dumped,
1496+
{
1497+
"data": {
1498+
"type": "AllTypes",
1499+
"id": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1500+
"attributes": {
1501+
"all_types_pk": "c578ccd6-3dd0-4315-87f3-e200d80dd6f9",
1502+
"time_only": "2023-10-10",
1503+
},
1504+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1505+
},
1506+
"links": {"self": "/forest/AllTypes/c578ccd6-3dd0-4315-87f3-e200d80dd6f9"},
1507+
},
1508+
)

0 commit comments

Comments
 (0)