# Buggy code
def decode(obj):
    """
    Decoder for deserializing numpy data types.
    """

    typ = obj.get("typ")
    if typ is None:
        return obj
    elif typ == "timestamp":
        freq = obj["freq"] if "freq" in obj else obj["offset"]
        return Timestamp(obj["value"], tz=obj["tz"], freq=freq)
    elif typ == "nat":
        return NaT
    elif typ == "period":
        return Period(ordinal=obj["ordinal"], freq=obj["freq"])
    elif typ == "index":
        dtype = dtype_for(obj["dtype"])
        data = unconvert(obj["data"], dtype, obj.get("compress"))
        return globals()[obj["klass"]](data, dtype=dtype, name=obj["name"])
    elif typ == "range_index":
        return globals()[obj["klass"]](
            obj["start"], obj["stop"], obj["step"], name=obj["name"]
        )
    elif typ == "multi_index":
        dtype = dtype_for(obj["dtype"])
        data = unconvert(obj["data"], dtype, obj.get("compress"))
        data = [tuple(x) for x in data]
        return globals()[obj["klass"]].from_tuples(data, names=obj["names"])
    elif typ == "period_index":
        data = unconvert(obj["data"], np.int64, obj.get("compress"))
        d = dict(name=obj["name"], freq=obj["freq"])
        return globals()[obj["klass"]]._from_ordinals(data, **d)
    elif typ == "datetime_index":
        data = unconvert(obj["data"], np.int64, obj.get("compress"))
        d = dict(name=obj["name"], freq=obj["freq"], verify_integrity=False)
        result = globals()[obj["klass"]](data, **d)
        tz = obj["tz"]

        # reverse tz conversion
        if tz is not None:
            result = result.tz_localize("UTC").tz_convert(tz)
        return result

    elif typ == "category":
        from_codes = globals()[obj["klass"]].from_codes
        return from_codes(
            codes=obj["codes"], categories=obj["categories"], ordered=obj["ordered"]
        )

    elif typ == "series":
        dtype = dtype_for(obj["dtype"])
        pd_dtype = pandas_dtype(dtype)

        index = obj["index"]
        result = globals()[obj["klass"]](
            unconvert(obj["data"], dtype, obj["compress"]),
            index=index,
            dtype=pd_dtype,
            name=obj["name"],
        )
        return result

    elif typ == "block_manager":
        axes = obj["axes"]

        def create_block(b):
            values = _safe_reshape(
                unconvert(b["values"], dtype_for(b["dtype"]), b["compress"]), b["shape"]
            )

            # locs handles duplicate column names, and should be used instead
            # of items; see GH 9618
            if "locs" in b:
                placement = b["locs"]
            else:
                placement = axes[0].get_indexer(b["items"])
            return make_block(
                values=values,
                klass=getattr(internals, b["klass"]),
                placement=placement,
                dtype=b["dtype"],
            )

        blocks = [create_block(b) for b in obj["blocks"]]
        return globals()[obj["klass"]](BlockManager(blocks, axes))
    elif typ == "datetime":
        return parse(obj["data"])
    elif typ == "datetime64":
        return np.datetime64(parse(obj["data"]))
    elif typ == "date":
        return parse(obj["data"]).date()
    elif typ == "timedelta":
        return timedelta(*obj["data"])
    elif typ == "timedelta64":
        return np.timedelta64(int(obj["data"]))
    # elif typ == 'sparse_series':
    #    dtype = dtype_for(obj['dtype'])
    #    return globals()[obj['klass']](
    #        unconvert(obj['sp_values'], dtype, obj['compress']),
    #        sparse_index=obj['sp_index'], index=obj['index'],
    #        fill_value=obj['fill_value'], kind=obj['kind'], name=obj['name'])
    # elif typ == 'sparse_dataframe':
    #    return globals()[obj['klass']](
    #        obj['data'], columns=obj['columns'],
    #        default_fill_value=obj['default_fill_value'],
    #        default_kind=obj['default_kind']
    #    )
    # elif typ == 'sparse_panel':
    #    return globals()[obj['klass']](
    #        obj['data'], items=obj['items'],
    #        default_fill_value=obj['default_fill_value'],
    #        default_kind=obj['default_kind'])
    elif typ == "block_index":
        return globals()[obj["klass"]](obj["length"], obj["blocs"], obj["blengths"])
    elif typ == "int_index":
        return globals()[obj["klass"]](obj["length"], obj["indices"])
    elif typ == "ndarray":
        return unconvert(
            obj["data"], np.typeDict[obj["dtype"]], obj.get("compress")
        ).reshape(obj["shape"])
    elif typ == "np_scalar":
        if obj.get("sub_typ") == "np_complex":
            return c2f(obj["real"], obj["imag"], obj["dtype"])
        else:
            dtype = dtype_for(obj["dtype"])
            try:
                return dtype(obj["data"])
            except:
                return dtype.type(obj["data"])
    elif typ == "np_complex":
        return complex(obj["real"] + "+" + obj["imag"] + "j")
    elif isinstance(obj, (dict, list, set)):
        return obj
    else:
        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 decode(obj):
    """
    Decoder for deserializing numpy data types.
    """

    typ = obj.get("typ")
    if typ is None:
        return obj
    elif typ == "timestamp":
        freq = obj["freq"] if "freq" in obj else obj["offset"]
        return Timestamp(obj["value"], tz=obj["tz"], freq=freq)
    elif typ == "nat":
        return NaT
    elif typ == "period":
        return Period(ordinal=obj["ordinal"], freq=obj["freq"])
    elif typ == "index":
        dtype = dtype_for(obj["dtype"])
        data = unconvert(obj["data"], dtype, obj.get("compress"))
        return globals()[obj["klass"]](data, dtype=dtype, name=obj["name"])
    elif typ == "range_index":
        return globals()[obj["klass"]](
            obj["start"], obj["stop"], obj["step"], name=obj["name"]
        )
    elif typ == "multi_index":
        dtype = dtype_for(obj["dtype"])
        data = unconvert(obj["data"], dtype, obj.get("compress"))
        data = [tuple(x) for x in data]
        return globals()[obj["klass"]].from_tuples(data, names=obj["names"])
    elif typ == "period_index":
        data = unconvert(obj["data"], np.int64, obj.get("compress"))
        d = dict(name=obj["name"], freq=obj["freq"])
        return globals()[obj["klass"]]._from_ordinals(data, **d)
    elif typ == "datetime_index":
        data = unconvert(obj["data"], np.int64, obj.get("compress"))
        d = dict(name=obj["name"], freq=obj["freq"], verify_integrity=False)
        result = globals()[obj["klass"]](data, **d)
        tz = obj["tz"]

        # reverse tz conversion
        if tz is not None:
            result = result.tz_localize("UTC").tz_convert(tz)
        return result

    elif typ == "interval_index":
        return globals()[obj["klass"]].from_arrays(
            obj["left"], obj["right"], obj["closed"], name=obj["name"]
        )
    elif typ == "category":
        from_codes = globals()[obj["klass"]].from_codes
        return from_codes(
            codes=obj["codes"], categories=obj["categories"], ordered=obj["ordered"]
        )

    elif typ == "interval":
        return Interval(obj["left"], obj["right"], obj["closed"])
    elif typ == "series":
        dtype = dtype_for(obj["dtype"])
        pd_dtype = pandas_dtype(dtype)

        index = obj["index"]
        result = globals()[obj["klass"]](
            unconvert(obj["data"], dtype, obj["compress"]),
            index=index,
            dtype=pd_dtype,
            name=obj["name"],
        )
        return result

    elif typ == "block_manager":
        axes = obj["axes"]

        def create_block(b):
            values = _safe_reshape(
                unconvert(b["values"], dtype_for(b["dtype"]), b["compress"]), b["shape"]
            )

            # locs handles duplicate column names, and should be used instead
            # of items; see GH 9618
            if "locs" in b:
                placement = b["locs"]
            else:
                placement = axes[0].get_indexer(b["items"])
            return make_block(
                values=values,
                klass=getattr(internals, b["klass"]),
                placement=placement,
                dtype=b["dtype"],
            )

        blocks = [create_block(b) for b in obj["blocks"]]
        return globals()[obj["klass"]](BlockManager(blocks, axes))
    elif typ == "datetime":
        return parse(obj["data"])
    elif typ == "datetime64":
        return np.datetime64(parse(obj["data"]))
    elif typ == "date":
        return parse(obj["data"]).date()
    elif typ == "timedelta":
        return timedelta(*obj["data"])
    elif typ == "timedelta64":
        return np.timedelta64(int(obj["data"]))
    # elif typ == 'sparse_series':
    #    dtype = dtype_for(obj['dtype'])
    #    return globals()[obj['klass']](
    #        unconvert(obj['sp_values'], dtype, obj['compress']),
    #        sparse_index=obj['sp_index'], index=obj['index'],
    #        fill_value=obj['fill_value'], kind=obj['kind'], name=obj['name'])
    # elif typ == 'sparse_dataframe':
    #    return globals()[obj['klass']](
    #        obj['data'], columns=obj['columns'],
    #        default_fill_value=obj['default_fill_value'],
    #        default_kind=obj['default_kind']
    #    )
    # elif typ == 'sparse_panel':
    #    return globals()[obj['klass']](
    #        obj['data'], items=obj['items'],
    #        default_fill_value=obj['default_fill_value'],
    #        default_kind=obj['default_kind'])
    elif typ == "block_index":
        return globals()[obj["klass"]](obj["length"], obj["blocs"], obj["blengths"])
    elif typ == "int_index":
        return globals()[obj["klass"]](obj["length"], obj["indices"])
    elif typ == "ndarray":
        return unconvert(
            obj["data"], np.typeDict[obj["dtype"]], obj.get("compress")
        ).reshape(obj["shape"])
    elif typ == "np_scalar":
        if obj.get("sub_typ") == "np_complex":
            return c2f(obj["real"], obj["imag"], obj["dtype"])
        else:
            dtype = dtype_for(obj["dtype"])
            try:
                return dtype(obj["data"])
            except:
                return dtype.type(obj["data"])
    elif typ == "np_complex":
        return complex(obj["real"] + "+" + obj["imag"] + "j")
    elif isinstance(obj, (dict, list, set)):
        return obj
    else:
        return obj