docs: def _UnserializableObjectFallback(self, obj):
      """Handles sanitizing of unserializable objects for Json.
  
      For instances of heap types, we take the class dict, augment it with the
      instance's __dict__, tag it and transmit it over to the RPC client to be
      reconstructed there. (Works with both old and new style classes)
      Args:
        obj: The object to Json-serialize
      Returns:
        A Json-serializable version of the parameter
      """
      if isinstance(obj, libpython.PyInstanceObjectPtr):
        # old-style classes use 'classobj'/'instance'
        # get class attribute dictionary
        in_class = obj.pyop_field('in_class')
        result_dict = in_class.pyop_field('cl_dict').proxyval(set())
  
        # let libpython.py do the work of getting the instance dict
        instanceproxy = obj.proxyval(set())
        result_dict.update(instanceproxy.attrdict)
        result_dict['__pyringe_type_name__'] = instanceproxy.cl_name
        result_dict['__pyringe_address__'] = instanceproxy.address
        return result_dict
  
      if isinstance(obj, libpython.HeapTypeObjectPtr):
        # interestingly enough, HeapTypeObjectPtr seems to handle all pointers to
        # heap type PyObjects, not only pointers to PyHeapTypeObject. This
        # corresponds to new-style class instances. However, as all instances of
        # new-style classes are simple PyObject pointers to the interpreter,
        # libpython.py tends to give us HeapTypeObjectPtrs for things we can't
        # handle properly.
  
        try:
          # get class attribute dictionary
          type_ptr = obj.field('ob_type')
          tp_dict = type_ptr.cast(GdbCache.TYPE)['tp_dict'].cast(GdbCache.DICT)
          result_dict = libpython.PyDictObjectPtr(tp_dict).proxyval(set())
        except gdb.error:
          # There was probably a type mismatch triggered by wrong assumptions in
          # libpython.py
          result_dict = {}
  
        try:
          # get instance attributes
          result_dict.update(obj.get_attr_dict().proxyval(set()))
          result_dict['__pyringe_type_name__'] = obj.safe_tp_name()
          result_dict['__pyringe_address__'] = long(obj._gdbval)  # pylint: disable=protected-access
          return result_dict
        except TypeError:
          # This happens in the case where we're not really looking at a heap type
          # instance. There isn't really anything we can do, so we fall back to
          # the default handling.
          pass
      # Default handler -- this does not result in proxy objects or fancy dicts,
      # but most of the time, we end up emitting strings of the format
      # '<object at remote 0x345a235>'
      try:
        proxy = obj.proxyval(set())
        # json doesn't accept non-strings as keys, so we're helping along
        if isinstance(proxy, dict):
          return {str(key): val for key, val in proxy.iteritems()}
        return proxy
      except AttributeError:
        return str(obj)