From e3b296c558dcad4f77b6c82c37ed20903b1699bf Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Thu, 5 Jan 2017 18:56:07 +0100 Subject: [PATCH] utils: teach our json serializer to handle more types (#1907) Namely datetime.time and numpy.bool_ Refs: #1900 Refs: #1903 --- superset/utils.py | 6 +++- tests/utils_tests.py | 71 +++++++++++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/superset/utils.py b/superset/utils.py index 9239b71b581ae..aa6df9120dc2a 100644 --- a/superset/utils.py +++ b/superset/utils.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals from builtins import object -from datetime import date, datetime +from datetime import date, datetime, time import decimal import functools import json @@ -216,6 +216,8 @@ def base_json_conv(obj): if isinstance(obj, numpy.int64): return int(obj) + elif isinstance(obj, numpy.bool_): + return bool(obj) elif isinstance(obj, set): return list(obj) elif isinstance(obj, decimal.Decimal): @@ -239,6 +241,8 @@ def json_iso_dttm_ser(obj): obj = obj.isoformat() elif isinstance(obj, date): obj = obj.isoformat() + elif isinstance(obj, time): + obj = obj.isoformat() else: raise TypeError( "Unserializable object {} of type {}".format(obj, type(obj)) diff --git a/tests/utils_tests.py b/tests/utils_tests.py index 0cb61a66233ff..bac0a7b80d8dd 100644 --- a/tests/utils_tests.py +++ b/tests/utils_tests.py @@ -1,24 +1,47 @@ -from datetime import datetime, date, timedelta -from superset import utils -import unittest - -from mock import Mock, patch - -class UtilsTestCase(unittest.TestCase): - def test_json_int_dttm_ser(self): - dttm = datetime(2020, 1, 1) - ts = 1577836800000.0 - json_int_dttm_ser = utils.json_int_dttm_ser - assert json_int_dttm_ser(dttm) == ts - assert json_int_dttm_ser(date(2020, 1, 1)) == ts - assert json_int_dttm_ser(datetime(1970, 1, 1)) == 0 - assert json_int_dttm_ser(date(1970, 1, 1)) == 0 - assert json_int_dttm_ser(dttm + timedelta(milliseconds=1)) == (ts + 1) - - with self.assertRaises(TypeError): - utils.json_int_dttm_ser("this is not a date") - - @patch('superset.utils.datetime') - def test_parse_human_timedelta(self, mock_now): - mock_now.return_value = datetime(2016, 12, 1) - self.assertEquals(utils.parse_human_timedelta('now'), timedelta(0)) +from datetime import datetime, date, timedelta, time +from decimal import Decimal +from superset.utils import ( + json_int_dttm_ser, json_iso_dttm_ser, base_json_conv, parse_human_timedelta +) +import unittest +import uuid + +from mock import Mock, patch +import numpy + + +class UtilsTestCase(unittest.TestCase): + def test_json_int_dttm_ser(self): + dttm = datetime(2020, 1, 1) + ts = 1577836800000.0 + assert json_int_dttm_ser(dttm) == ts + assert json_int_dttm_ser(date(2020, 1, 1)) == ts + assert json_int_dttm_ser(datetime(1970, 1, 1)) == 0 + assert json_int_dttm_ser(date(1970, 1, 1)) == 0 + assert json_int_dttm_ser(dttm + timedelta(milliseconds=1)) == (ts + 1) + + with self.assertRaises(TypeError): + json_int_dttm_ser("this is not a date") + + def test_json_iso_dttm_ser(self): + dttm = datetime(2020, 1, 1) + dt = date(2020, 1, 1) + t = time() + assert json_iso_dttm_ser(dttm) == dttm.isoformat() + assert json_iso_dttm_ser(dt) == dt.isoformat() + assert json_iso_dttm_ser(t) == t.isoformat() + + with self.assertRaises(TypeError): + json_iso_dttm_ser("this is not a date") + + def test_base_json_conv(self): + assert isinstance(base_json_conv(numpy.bool_(1)), bool) == True + assert isinstance(base_json_conv(numpy.int64(1)), int) == True + assert isinstance(base_json_conv(set([1])), list) == True + assert isinstance(base_json_conv(Decimal('1.0')), float) == True + assert isinstance(base_json_conv(uuid.uuid4()), str) == True + + @patch('superset.utils.datetime') + def test_parse_human_timedelta(self, mock_now): + mock_now.return_value = datetime(2016, 12, 1) + self.assertEquals(parse_human_timedelta('now'), timedelta(0))