66import inspect
77import json
88import traceback
9+ from collections .abc import MutableMapping
910
1011import reframe .utility as util
1112
@@ -17,10 +18,30 @@ def __rfm_json_encode__(self):
1718 '__rfm_file__' : inspect .getfile (type (self ))
1819 }
1920 ret .update (self .__dict__ )
20- return ret
21+ encoded_ret = encode_dict (ret , recursive = True )
22+ return encoded_ret if encoded_ret else ret
2123
2224
23- def encode (obj ):
25+ def encode_dict (obj , * , recursive = False ):
26+ '''Transform tuple dict keys into strings.
27+
28+ Use the recursive option to also check the keys in nested dicts.
29+ '''
30+ # FIXME: Need to add support for a decode_dict functionality
31+ if isinstance (obj , MutableMapping ):
32+ if recursive or any (isinstance (k , tuple ) for k in obj ):
33+ newobj = type (obj )()
34+ for k , v in obj .items ():
35+ _key = str (k ) if isinstance (k , tuple ) else k
36+ _v = encode_dict (v , recursive = recursive )
37+ newobj [_key ] = _v if _v is not None else v
38+
39+ return newobj
40+
41+ return None
42+
43+
44+ def encode (obj , ** kwargs ):
2445 if hasattr (obj , '__rfm_json_encode__' ):
2546 return obj .__rfm_json_encode__ ()
2647
@@ -37,17 +58,27 @@ def encode(obj):
3758 if inspect .istraceback (obj ):
3859 return traceback .format_tb (obj )
3960
61+ newobj = encode_dict (obj )
62+ if newobj is not None :
63+ return newobj
64+
4065 return None
4166
4267
4368def dump (obj , fp , ** kwargs ):
4469 kwargs .setdefault ('default' , encode )
45- return json .dump (obj , fp , ** kwargs )
70+ try :
71+ return json .dump (obj , fp , ** kwargs )
72+ except TypeError :
73+ return json .dump (encode (obj ), fp , ** kwargs )
4674
4775
4876def dumps (obj , ** kwargs ):
4977 kwargs .setdefault ('default' , encode )
50- return json .dumps (obj , ** kwargs )
78+ try :
79+ return json .dumps (obj , ** kwargs )
80+ except TypeError :
81+ return json .dumps (encode (obj ), ** kwargs )
5182
5283
5384def _object_hook (json ):
0 commit comments