# Buggy code
def loads(buf):
    mv = memoryview(buf)
    header = read_file_header(mv)
    compress = header.compress

    if compress == CompressType.NONE:
        data = buf[HEADER_LENGTH:]
    else:
        data = decompressors[compress](mv[HEADER_LENGTH:])

    if header.type == SerialType.ARROW:
        try:
            return deserialize(memoryview(data))
        except pyarrow.lib.ArrowInvalid:  # pragma: no cover
            # reconstruct value from buffers of arrow components
            data_view = memoryview(data)
            meta_block_size = np.frombuffer(data_view[0:4], dtype="int32").item()
            meta = pickle.loads(data_view[4 : 4 + meta_block_size])  # nosec
            buffer_sizes = meta.pop("buffer_sizes")
            bounds = np.cumsum([4 + meta_block_size] + buffer_sizes)
            meta["data"] = [
                pyarrow.py_buffer(data_view[bounds[idx] : bounds[idx + 1]])
                for idx in range(len(buffer_sizes))
            ]
            return pyarrow.deserialize_components(meta, mars_serialize_context())
    else:
        return pickle.loads(data)


# Traceback (AttributeError)
In [4]: df.sort_values(by='col1').execute()
Out[4]: ---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~/miniconda3/lib/python3.7/site-packages/IPython/core/formatters.py in __call__(self, obj)
700                 type_pprinters=self.type_printers,
701                 deferred_pprinters=self.deferred_printers)
--> 702             printer.pretty(obj)
703             printer.flush()
704             return stream.getvalue()

~/miniconda3/lib/python3.7/site-packages/IPython/lib/pretty.py in pretty(self, obj)
392                         if cls is not object \
393                                 and callable(cls.__dict__.get('__repr__')):
--> 394                             return _repr_pprint(obj, self, cycle)
395
396             return _default_pprint(obj, self, cycle)

~/miniconda3/lib/python3.7/site-packages/IPython/lib/pretty.py in _repr_pprint(obj, p, cycle)
698     """A pprint that just redirects to the normal repr function."""
699     # Find newlines and replace them with p.break_()
--> 700     output = repr(obj)
701     lines = output.splitlines()
702     with p.group():

~/Documents/mars_dev/mars/mars/core.py in __repr__(self)
129
130     def __repr__(self):
--> 131         return self._data.__repr__()
132
133     def _check_data(self, data):

~/Documents/mars_dev/mars/mars/dataframe/core.py in __repr__(self)
1084
1085     def __repr__(self):
-> 1086         return self._to_str(representation=True)
1087
1088     def _repr_html_(self):

~/Documents/mars_dev/mars/mars/dataframe/core.py in _to_str(self, representation)
1057         else:
1058             corner_data = fetch_corner_data(
-> 1059                 self, session=self._executed_sessions[-1])
1060
1061             buf = StringIO()

~/Documents/mars_dev/mars/mars/dataframe/utils.py in fetch_corner_data(df_or_series, session)
895         head_data, tail_data = \
896             ExecutableTuple([head, tail]).fetch(session=session)
--> 897         return pd.concat([head_data, tail_data], axis='index')
898
899

~/miniconda3/lib/python3.7/site-packages/pandas/core/reshape/concat.py in concat(objs, axis, join, ignore_index, keys, levels, names, verify_integrity, sort, copy)
279         verify_integrity=verify_integrity,
280         copy=copy,
--> 281         sort=sort,
282     )
283

~/miniconda3/lib/python3.7/site-packages/pandas/core/reshape/concat.py in __init__(self, objs, axis, join, keys, levels, names, ignore_index, verify_integrity, copy, sort)
358
359             # consolidate
--> 360             obj._consolidate(inplace=True)
361             ndims.add(obj.ndim)
362

~/miniconda3/lib/python3.7/site-packages/pandas/core/generic.py in _consolidate(self, inplace)
5363         inplace = validate_bool_kwarg(inplace, "inplace")
5364         if inplace:
-> 5365             self._consolidate_inplace()
5366         else:
5367             f = lambda: self._data.consolidate()

~/miniconda3/lib/python3.7/site-packages/pandas/core/generic.py in _consolidate_inplace(self)
5345             self._data = self._data.consolidate()
5346
-> 5347         self._protect_consolidate(f)
5348
5349     def _consolidate(self, inplace: bool_t = False):

~/miniconda3/lib/python3.7/site-packages/pandas/core/generic.py in _protect_consolidate(self, f)
5333         cache
5334         """
-> 5335         blocks_before = len(self._data.blocks)
5336         result = f()
5337         if len(self._data.blocks) != blocks_before:

~/miniconda3/lib/python3.7/site-packages/pandas/core/generic.py in __getattr__(self, name)
5268             or name in self._accessors
5269         ):
-> 5270             return object.__getattribute__(self, name)
5271         else:
5272             if self._info_axis._can_hold_identifiers_and_holds_name(name):

AttributeError: 'DataFrame' object has no attribute '_data'

# Fixed code
def loads(buf):
    mv = memoryview(buf)
    header = read_file_header(mv)
    compress = header.compress

    if compress == CompressType.NONE:
        data = buf[HEADER_LENGTH:]
    else:
        data = decompressors[compress](mv[HEADER_LENGTH:])

    if header.type == SerialType.ARROW:
        try:
            return deserialize(memoryview(data))
        except pyarrow.lib.ArrowInvalid:  # pragma: no cover
            # reconstruct value from buffers of arrow components
            data_view = memoryview(data)
            meta_block_size = np.frombuffer(data_view[0:4], dtype="int32").item()
            meta = pickle.loads(data_view[4 : 4 + meta_block_size])  # nosec
            buffer_sizes = meta.pop("buffer_sizes")
            bounds = np.cumsum([4 + meta_block_size] + buffer_sizes)
            meta["data"] = [
                pyarrow.py_buffer(data_view[bounds[idx] : bounds[idx + 1]])
                for idx in range(len(buffer_sizes))
            ]
            return _patch_pandas_mgr(
                pyarrow.deserialize_components(meta, mars_serialize_context())
            )
    else:
        return _patch_pandas_mgr(pickle.loads(data))  # nosec