# Buggy code
def encode(obj):
    """
    Data encoder
    """
    tobj = type(obj)
    if isinstance(obj, Index):
        if isinstance(obj, RangeIndex):
            return {
                "typ": "range_index",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "start": getattr(obj, "_start", None),
                "stop": getattr(obj, "_stop", None),
                "step": getattr(obj, "_step", None),
            }
        elif isinstance(obj, PeriodIndex):
            return {
                "typ": "period_index",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "freq": u_safe(getattr(obj, "freqstr", None)),
                "dtype": u(obj.dtype.name),
                "data": convert(obj.asi8),
                "compress": compressor,
            }
        elif isinstance(obj, DatetimeIndex):
            tz = getattr(obj, "tz", None)

            # store tz info and data as UTC
            if tz is not None:
                tz = u(tz.zone)
                obj = obj.tz_convert("UTC")
            return {
                "typ": "datetime_index",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "dtype": u(obj.dtype.name),
                "data": convert(obj.asi8),
                "freq": u_safe(getattr(obj, "freqstr", None)),
                "tz": tz,
                "compress": compressor,
            }
        elif isinstance(obj, MultiIndex):
            return {
                "typ": "multi_index",
                "klass": u(obj.__class__.__name__),
                "names": getattr(obj, "names", None),
                "dtype": u(obj.dtype.name),
                "data": convert(obj.values),
                "compress": compressor,
            }
        else:
            return {
                "typ": "index",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "dtype": u(obj.dtype.name),
                "data": convert(obj.values),
                "compress": compressor,
            }

    elif isinstance(obj, Categorical):
        return {
            "typ": "category",
            "klass": u(obj.__class__.__name__),
            "name": getattr(obj, "name", None),
            "codes": obj.codes,
            "categories": obj.categories,
            "ordered": obj.ordered,
            "compress": compressor,
        }

    elif isinstance(obj, Series):
        if isinstance(obj, SparseSeries):
            raise NotImplementedError("msgpack sparse series is not implemented")
            # d = {'typ': 'sparse_series',
            #     'klass': obj.__class__.__name__,
            #     'dtype': obj.dtype.name,
            #     'index': obj.index,
            #     'sp_index': obj.sp_index,
            #     'sp_values': convert(obj.sp_values),
            #     'compress': compressor}
            # for f in ['name', 'fill_value', 'kind']:
            #    d[f] = getattr(obj, f, None)
            # return d
        else:
            return {
                "typ": "series",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "index": obj.index,
                "dtype": u(obj.dtype.name),
                "data": convert(obj.values),
                "compress": compressor,
            }
    elif issubclass(tobj, NDFrame):
        if isinstance(obj, SparseDataFrame):
            raise NotImplementedError("msgpack sparse frame is not implemented")
            # d = {'typ': 'sparse_dataframe',
            #     'klass': obj.__class__.__name__,
            #     'columns': obj.columns}
            # for f in ['default_fill_value', 'default_kind']:
            #    d[f] = getattr(obj, f, None)
            # d['data'] = dict([(name, ss)
            #                 for name, ss in compat.iteritems(obj)])
            # return d
        else:
            data = obj._data
            if not data.is_consolidated():
                data = data.consolidate()

            # the block manager
            return {
                "typ": "block_manager",
                "klass": u(obj.__class__.__name__),
                "axes": data.axes,
                "blocks": [
                    {
                        "locs": b.mgr_locs.as_array,
                        "values": convert(b.values),
                        "shape": b.values.shape,
                        "dtype": u(b.dtype.name),
                        "klass": u(b.__class__.__name__),
                        "compress": compressor,
                    }
                    for b in data.blocks
                ],
            }

    elif (
        isinstance(obj, (datetime, date, np.datetime64, timedelta, np.timedelta64))
        or obj is NaT
    ):
        if isinstance(obj, Timestamp):
            tz = obj.tzinfo
            if tz is not None:
                tz = u(tz.zone)
            freq = obj.freq
            if freq is not None:
                freq = u(freq.freqstr)
            return {"typ": "timestamp", "value": obj.value, "freq": freq, "tz": tz}
        if obj is NaT:
            return {"typ": "nat"}
        elif isinstance(obj, np.timedelta64):
            return {"typ": "timedelta64", "data": obj.view("i8")}
        elif isinstance(obj, timedelta):
            return {
                "typ": "timedelta",
                "data": (obj.days, obj.seconds, obj.microseconds),
            }
        elif isinstance(obj, np.datetime64):
            return {"typ": "datetime64", "data": u(str(obj))}
        elif isinstance(obj, datetime):
            return {"typ": "datetime", "data": u(obj.isoformat())}
        elif isinstance(obj, date):
            return {"typ": "date", "data": u(obj.isoformat())}
        raise Exception("cannot encode this datetimelike object: %s" % obj)
    elif isinstance(obj, Period):
        return {"typ": "period", "ordinal": obj.ordinal, "freq": u(obj.freq)}
    elif isinstance(obj, BlockIndex):
        return {
            "typ": "block_index",
            "klass": u(obj.__class__.__name__),
            "blocs": obj.blocs,
            "blengths": obj.blengths,
            "length": obj.length,
        }
    elif isinstance(obj, IntIndex):
        return {
            "typ": "int_index",
            "klass": u(obj.__class__.__name__),
            "indices": obj.indices,
            "length": obj.length,
        }
    elif isinstance(obj, np.ndarray):
        return {
            "typ": "ndarray",
            "shape": obj.shape,
            "ndim": obj.ndim,
            "dtype": u(obj.dtype.name),
            "data": convert(obj),
            "compress": compressor,
        }
    elif isinstance(obj, np.number):
        if np.iscomplexobj(obj):
            return {
                "typ": "np_scalar",
                "sub_typ": "np_complex",
                "dtype": u(obj.dtype.name),
                "real": u(obj.real.__repr__()),
                "imag": u(obj.imag.__repr__()),
            }
        else:
            return {
                "typ": "np_scalar",
                "dtype": u(obj.dtype.name),
                "data": u(obj.__repr__()),
            }
    elif isinstance(obj, complex):
        return {
            "typ": "np_complex",
            "real": u(obj.real.__repr__()),
            "imag": u(obj.imag.__repr__()),
        }

    return obj


# Traceback (TypeError)
import pandas as pd
pd.DataFrame({'C': pd.period_range('2015-01-01', periods=3)}).to_msgpack()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-65-8e5ad9cd6036> in <module>()
----> 1 pd.DataFrame({'C': pd.period_range('2015-01-01', periods=3)}).to_msgpack()

/auto/energymdl2/anaconda/envs/commod_20160516_pd18/lib/python2.7/site-packages/pandas/core/generic.pyc in to_msgpack(self, path_or_buf, encoding, **kwargs)
1120         from pandas.io import packers
1121         return packers.to_msgpack(path_or_buf, self, encoding=encoding,
-> 1122                                   **kwargs)
1123
1124     def to_sql(self, name, con, flavor='sqlite', schema=None, if_exists='fail',

/auto/energymdl2/anaconda/envs/commod_20160516_pd18/lib/python2.7/site-packages/pandas/io/packers.pyc in to_msgpack(path_or_buf, *args, **kwargs)
152     elif path_or_buf is None:
153         buf = compat.BytesIO()
--> 154         writer(buf)
155         return buf.getvalue()
156     else:

/auto/energymdl2/anaconda/envs/commod_20160516_pd18/lib/python2.7/site-packages/pandas/io/packers.pyc in writer(fh)
145     def writer(fh):
146         for a in args:
--> 147             fh.write(pack(a, **kwargs))
148
149     if isinstance(path_or_buf, compat.string_types):

/auto/energymdl2/anaconda/envs/commod_20160516_pd18/lib/python2.7/site-packages/pandas/io/packers.pyc in pack(o, default, encoding, unicode_errors, use_single_float, autoreset, use_bin_type)
699                   use_single_float=use_single_float,
700                   autoreset=autoreset,
--> 701                   use_bin_type=use_bin_type).pack(o)
702
703

pandas/msgpack/_packer.pyx in pandas.msgpack._packer.Packer.pack (pandas/msgpack/_packer.cpp:3434)()

pandas/msgpack/_packer.pyx in pandas.msgpack._packer.Packer.pack (pandas/msgpack/_packer.cpp:3276)()

pandas/msgpack/_packer.pyx in pandas.msgpack._packer.Packer._pack (pandas/msgpack/_packer.cpp:2433)()

pandas/msgpack/_packer.pyx in pandas.msgpack._packer.Packer._pack (pandas/msgpack/_packer.cpp:3006)()

pandas/msgpack/_packer.pyx in pandas.msgpack._packer.Packer._pack (pandas/msgpack/_packer.cpp:2433)()

pandas/msgpack/_packer.pyx in pandas.msgpack._packer.Packer._pack (pandas/msgpack/_packer.cpp:3006)()

pandas/msgpack/_packer.pyx in pandas.msgpack._packer.Packer._pack (pandas/msgpack/_packer.cpp:3088)()

/auto/energymdl2/anaconda/envs/commod_20160516_pd18/lib/python2.7/site-packages/pandas/io/packers.pyc in encode(obj)
510         return {u'typ': u'period',
511                 u'ordinal': obj.ordinal,
--> 512                 u'freq': u(obj.freq)}
513     elif isinstance(obj, BlockIndex):
514         return {u'typ': u'block_index',

/auto/energymdl2/anaconda/envs/commod_20160516_pd18/lib/python2.7/site-packages/pandas/compat/__init__.pyc in u(s)
262
263     def u(s):
--> 264         return unicode(s, "unicode_escape")
265
266     def u_safe(s):

TypeError: coercing to Unicode: need string or buffer, Day found

# Fixed code
def encode(obj):
    """
    Data encoder
    """
    tobj = type(obj)
    if isinstance(obj, Index):
        if isinstance(obj, RangeIndex):
            return {
                "typ": "range_index",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "start": getattr(obj, "_start", None),
                "stop": getattr(obj, "_stop", None),
                "step": getattr(obj, "_step", None),
            }
        elif isinstance(obj, PeriodIndex):
            return {
                "typ": "period_index",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "freq": u_safe(getattr(obj, "freqstr", None)),
                "dtype": u(obj.dtype.name),
                "data": convert(obj.asi8),
                "compress": compressor,
            }
        elif isinstance(obj, DatetimeIndex):
            tz = getattr(obj, "tz", None)

            # store tz info and data as UTC
            if tz is not None:
                tz = u(tz.zone)
                obj = obj.tz_convert("UTC")
            return {
                "typ": "datetime_index",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "dtype": u(obj.dtype.name),
                "data": convert(obj.asi8),
                "freq": u_safe(getattr(obj, "freqstr", None)),
                "tz": tz,
                "compress": compressor,
            }
        elif isinstance(obj, IntervalIndex):
            return {
                "typ": "interval_index",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "left": getattr(obj, "_left", None),
                "right": getattr(obj, "_right", None),
                "closed": getattr(obj, "_closed", None),
            }
        elif isinstance(obj, MultiIndex):
            return {
                "typ": "multi_index",
                "klass": u(obj.__class__.__name__),
                "names": getattr(obj, "names", None),
                "dtype": u(obj.dtype.name),
                "data": convert(obj.values),
                "compress": compressor,
            }
        else:
            return {
                "typ": "index",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "dtype": u(obj.dtype.name),
                "data": convert(obj.values),
                "compress": compressor,
            }

    elif isinstance(obj, Categorical):
        return {
            "typ": "category",
            "klass": u(obj.__class__.__name__),
            "name": getattr(obj, "name", None),
            "codes": obj.codes,
            "categories": obj.categories,
            "ordered": obj.ordered,
            "compress": compressor,
        }

    elif isinstance(obj, Series):
        if isinstance(obj, SparseSeries):
            raise NotImplementedError("msgpack sparse series is not implemented")
            # d = {'typ': 'sparse_series',
            #     'klass': obj.__class__.__name__,
            #     'dtype': obj.dtype.name,
            #     'index': obj.index,
            #     'sp_index': obj.sp_index,
            #     'sp_values': convert(obj.sp_values),
            #     'compress': compressor}
            # for f in ['name', 'fill_value', 'kind']:
            #    d[f] = getattr(obj, f, None)
            # return d
        else:
            return {
                "typ": "series",
                "klass": u(obj.__class__.__name__),
                "name": getattr(obj, "name", None),
                "index": obj.index,
                "dtype": u(obj.dtype.name),
                "data": convert(obj.values),
                "compress": compressor,
            }
    elif issubclass(tobj, NDFrame):
        if isinstance(obj, SparseDataFrame):
            raise NotImplementedError("msgpack sparse frame is not implemented")
            # d = {'typ': 'sparse_dataframe',
            #     'klass': obj.__class__.__name__,
            #     'columns': obj.columns}
            # for f in ['default_fill_value', 'default_kind']:
            #    d[f] = getattr(obj, f, None)
            # d['data'] = dict([(name, ss)
            #                 for name, ss in compat.iteritems(obj)])
            # return d
        else:
            data = obj._data
            if not data.is_consolidated():
                data = data.consolidate()

            # the block manager
            return {
                "typ": "block_manager",
                "klass": u(obj.__class__.__name__),
                "axes": data.axes,
                "blocks": [
                    {
                        "locs": b.mgr_locs.as_array,
                        "values": convert(b.values),
                        "shape": b.values.shape,
                        "dtype": u(b.dtype.name),
                        "klass": u(b.__class__.__name__),
                        "compress": compressor,
                    }
                    for b in data.blocks
                ],
            }

    elif (
        isinstance(obj, (datetime, date, np.datetime64, timedelta, np.timedelta64))
        or obj is NaT
    ):
        if isinstance(obj, Timestamp):
            tz = obj.tzinfo
            if tz is not None:
                tz = u(tz.zone)
            freq = obj.freq
            if freq is not None:
                freq = u(freq.freqstr)
            return {"typ": "timestamp", "value": obj.value, "freq": freq, "tz": tz}
        if obj is NaT:
            return {"typ": "nat"}
        elif isinstance(obj, np.timedelta64):
            return {"typ": "timedelta64", "data": obj.view("i8")}
        elif isinstance(obj, timedelta):
            return {
                "typ": "timedelta",
                "data": (obj.days, obj.seconds, obj.microseconds),
            }
        elif isinstance(obj, np.datetime64):
            return {"typ": "datetime64", "data": u(str(obj))}
        elif isinstance(obj, datetime):
            return {"typ": "datetime", "data": u(obj.isoformat())}
        elif isinstance(obj, date):
            return {"typ": "date", "data": u(obj.isoformat())}
        raise Exception("cannot encode this datetimelike object: %s" % obj)
    elif isinstance(obj, Period):
        return {"typ": "period", "ordinal": obj.ordinal, "freq": u_safe(obj.freqstr)}
    elif isinstance(obj, Interval):
        return {
            "typ": "interval",
            "left": obj.left,
            "right": obj.right,
            "closed": obj.closed,
        }
    elif isinstance(obj, BlockIndex):
        return {
            "typ": "block_index",
            "klass": u(obj.__class__.__name__),
            "blocs": obj.blocs,
            "blengths": obj.blengths,
            "length": obj.length,
        }
    elif isinstance(obj, IntIndex):
        return {
            "typ": "int_index",
            "klass": u(obj.__class__.__name__),
            "indices": obj.indices,
            "length": obj.length,
        }
    elif isinstance(obj, np.ndarray):
        return {
            "typ": "ndarray",
            "shape": obj.shape,
            "ndim": obj.ndim,
            "dtype": u(obj.dtype.name),
            "data": convert(obj),
            "compress": compressor,
        }
    elif isinstance(obj, np.number):
        if np.iscomplexobj(obj):
            return {
                "typ": "np_scalar",
                "sub_typ": "np_complex",
                "dtype": u(obj.dtype.name),
                "real": u(obj.real.__repr__()),
                "imag": u(obj.imag.__repr__()),
            }
        else:
            return {
                "typ": "np_scalar",
                "dtype": u(obj.dtype.name),
                "data": u(obj.__repr__()),
            }
    elif isinstance(obj, complex):
        return {
            "typ": "np_complex",
            "real": u(obj.real.__repr__()),
            "imag": u(obj.imag.__repr__()),
        }

    return obj