def denormalize(data):
if   data is None: return None<EOL>elif pimms.is_scalar(data, ('<STR_LIT>', '<STR_LIT:bool>', '<STR_LIT:string>', '<STR_LIT>')): return data<EOL>elif pimms.is_map(data):<EOL><INDENT>if normalize_type_key in data:<EOL><INDENT>(mdl,cls) = data[normalize_type_key]<EOL>if mdl is None:<EOL><INDENT>if   cls == '<STR_LIT>': return Ellipsis<EOL>elif cls == '<STR_LIT>':  return np.array(data['<STR_LIT>']) + <NUM_LIT>*np.array(data['<STR_LIT>'])<EOL>elif cls == '<STR_LIT>':      return set(denormalize(data['<STR_LIT>']))<EOL>elif cls == '<STR_LIT>':<EOL><INDENT>return sps.csr_matrix((data['<STR_LIT>'], (data['<STR_LIT>'],data['<STR_LIT>'])),<EOL>shape=data['<STR_LIT>'])<EOL><DEDENT>else: raise ValueError('<STR_LIT>' % cls)<EOL><DEDENT>else:<EOL><INDENT>cls = getattr(importlib.import_module(mdl), cls)<EOL>d = {k:denormalize(v) for (k,v) in six.iteritems(data) if k != normalize_type_key}<EOL>return cls.denormalize(d)<EOL><DEDENT><DEDENT>else: return {k:denormalize(v) for (k,v) in six.iteritems(data)} <EOL><DEDENT>else:<EOL><INDENT>if not hasattr(data, '<STR_LIT>'):<EOL><INDENT>msg = '<STR_LIT>' % (data, type(data))<EOL>raise ValueError(msg)<EOL><DEDENT>if pimms.is_array(data, ('<STR_LIT>', '<STR_LIT:bool>', '<STR_LIT:string>', '<STR_LIT>')): return data<EOL>return [denormalize(x) for x in data]<EOL><DEDENT>
denormalize(data) yield a denormalized version of the given JSON-friendly normalized data. This
  is the inverse of the normalize(obj) function.

The normalize and denormalize functions use the reserved keyword '__type__' along with the
<obj>.normalize() and <class>.denormalize(data) functions to manage types of objects that are
not JSON-compatible. Please see help(normalize) for more details.