diff --git a/qcodes/tests/test_helpers.py b/qcodes/tests/test_helpers.py index 6b056153b3a7..c4d5cad333b1 100644 --- a/qcodes/tests/test_helpers.py +++ b/qcodes/tests/test_helpers.py @@ -1,15 +1,19 @@ -from unittest import TestCase -import time -from datetime import datetime import asyncio import json +import time + +from collections import OrderedDict +from datetime import datetime +from unittest import TestCase + + import numpy as np from qcodes.utils.helpers import (is_sequence, permissive_range, wait_secs, make_unique, DelegateAttributes, LogCapture, strip_attrs, full_class, named_repr, make_sweep, is_sequence_of, - compare_dictionaries) + compare_dictionaries, NumpyJSONEncoder) from qcodes.utils.deferred_operations import is_function @@ -550,6 +554,38 @@ def test_depth(self): with self.subTest(args=args): self.assertFalse(is_sequence_of(*args)) +# tests related to JSON encoding +class TestJSONencoder(TestCase): + + def testNumpyJSONEncoder(self): + e = NumpyJSONEncoder() + + # test basic python types + od = OrderedDict() + od['a'] = 0 + od['b'] = 1 + testinput=[10, float(10.), 'hello', od] + testoutput=['10', '10.0', '"hello"', '{"a": 0, "b": 1}'] + # int + for d, r in zip(testinput, testoutput): + v=e.encode(d) + if type(d) == dict: + self.assertDictEqual(v, r) + else: + self.assertEqual(v, r) + + + # test numpy array + x=np.array([1,0,0]) + v=e.encode(x) + self.assertEqual(v, '[1, 0, 0]') + + # test class + class dummy(object): + pass + # test that does not raise, do not care about + # return value + e.encode(dummy()) class TestCompareDictionaries(TestCase): def test_same(self): diff --git a/qcodes/utils/helpers.py b/qcodes/utils/helpers.py index 3afea8cf22bc..37f8c3588d2b 100644 --- a/qcodes/utils/helpers.py +++ b/qcodes/utils/helpers.py @@ -18,6 +18,7 @@ class NumpyJSONEncoder(json.JSONEncoder): """Return numpy types as standard types.""" # http://stackoverflow.com/questions/27050108/convert-numpy-type-to-python # http://stackoverflow.com/questions/9452775/converting-numpy-dtypes-to-native-python-types/11389998#11389998 + def default(self, obj): if isinstance(obj, np.integer): return int(obj) @@ -33,7 +34,12 @@ def default(self, obj): 'im': float(obj.imag) } else: - return super(NumpyJSONEncoder, self).default(obj) + try: + s = super(NumpyJSONEncoder, self).default(obj) + except TypeError: + # we cannot convert the object to JSON, just take a string + s = str(obj) + return s def tprint(string, dt=1, tag='default'): diff --git a/qcodes/utils/validators.py b/qcodes/utils/validators.py index 80405a2c06a5..560ec694833f 100644 --- a/qcodes/utils/validators.py +++ b/qcodes/utils/validators.py @@ -364,7 +364,7 @@ def validate(self, value, context=''): if (np.shape(value) != self._shape): raise ValueError( '{} does not have expected shape {}; {}'.format( - repr(value), self._shape, context)) + repr(value), self._shape, context)) # Only check if max is not inf as it can be expensive for large arrays if self._max_value != (float("inf")):