# Buggy code
def _simple_new(cls, values, name=None, freq=None, **kwargs):
    """
    Create a new PeriodIndex.

    Parameters
    ----------
    values : PeriodArray, PeriodIndex, Index[int64], ndarray[int64]
        Values that can be converted to a PeriodArray without inference
        or coercion.

    """
    # TODO: raising on floats is tested, but maybe not useful.
    # Should the callers know not to pass floats?
    # At the very least, I think we can ensure that lists aren't passed.
    if isinstance(values, list):
        values = np.asarray(values)
    if is_float_dtype(values):
        raise TypeError("PeriodIndex._simple_new does not accept floats.")
    values = PeriodArray(values, freq=freq)

    if not isinstance(values, PeriodArray):
        raise TypeError("PeriodIndex._simple_new only accepts PeriodArray")
    result = object.__new__(cls)
    result._data = values
    result.name = name
    result._reset_identity()
    return result


# Traceback (AttributeError)
In [18]: s = pd.Series(np.random.rand(5), index=pd.date_range('20130101', periods=5))

In [19]: s
Out[19]:
2013-01-01    0.130706
2013-01-02    0.232104
2013-01-03    0.506547
2013-01-04    0.155568
2013-01-05    0.873604
Freq: D, dtype: float64

In [20]: s.to_msgpack('test.msg')

In [22]: s2 = pd.read_msgpack('test.msg')

In [23]: s2
Out[23]: ---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~/miniconda3/envs/dev/lib/python3.5/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/envs/dev/lib/python3.5/site-packages/IPython/lib/pretty.py in pretty(self, obj)
400                         if cls is not object \
401                                 and callable(cls.__dict__.get('__repr__')):
--> 402                             return _repr_pprint(obj, self, cycle)
403
404             return _default_pprint(obj, self, cycle)

~/miniconda3/envs/dev/lib/python3.5/site-packages/IPython/lib/pretty.py in _repr_pprint(obj, p, cycle)
695     """A pprint that just redirects to the normal repr function."""
696     # Find newlines and replace them with p.break_()
--> 697     output = repr(obj)
698     for idx,output_line in enumerate(output.splitlines()):
699         if idx:

~/scipy/pandas/pandas/core/base.py in __repr__(self)
75         Yields Bytestring in Py2, Unicode String in py3.
76         """
---> 77         return str(self)
78
79

~/scipy/pandas/pandas/core/base.py in __str__(self)
54
55         if compat.PY3:
---> 56             return self.__unicode__()
57         return self.__bytes__()
58

~/scipy/pandas/pandas/core/series.py in __unicode__(self)
1272
1273         self.to_string(buf=buf, name=self.name, dtype=self.dtype,
-> 1274                        max_rows=max_rows, length=show_dimensions)
1275         result = buf.getvalue()
1276

~/scipy/pandas/pandas/core/series.py in to_string(self, buf, na_rep, float_format, header, index, length, dtype, name, max_rows)
1316                                         float_format=float_format,
1317                                         max_rows=max_rows)
-> 1318         result = formatter.to_string()
1319
1320         # catch contract violations

~/scipy/pandas/pandas/io/formats/format.py in to_string(self)
258     def to_string(self):
259         series = self.tr_series
--> 260         footer = self._get_footer()
261
262         if len(series) == 0:

~/scipy/pandas/pandas/io/formats/format.py in _get_footer(self)
205
206         if getattr(self.series.index, 'freq', None) is not None:
--> 207             footer += 'Freq: {freq}'.format(freq=self.series.index.freqstr)
208
209         if self.name is not False and name is not None:

~/scipy/pandas/pandas/core/arrays/datetimelike.py in freqstr(self)
502         if self.freq is None:
503             return None
--> 504         return self.freq.freqstr
505
506     @property  # NB: override with cache_readonly in immutable subclasses

AttributeError: 'str' object has no attribute 'freqstr'

# Fixed code
def _simple_new(cls, values, name=None, freq=None, **kwargs):
    """
    Create a new PeriodIndex.

    Parameters
    ----------
    values : PeriodArray, PeriodIndex, Index[int64], ndarray[int64]
        Values that can be converted to a PeriodArray without inference
        or coercion.

    """
    # TODO: raising on floats is tested, but maybe not useful.
    # Should the callers know not to pass floats?
    # At the very least, I think we can ensure that lists aren't passed.
    if isinstance(values, list):
        values = np.asarray(values)
    if is_float_dtype(values):
        raise TypeError("PeriodIndex._simple_new does not accept floats.")
    if freq:
        freq = Period._maybe_convert_freq(freq)
    values = PeriodArray(values, freq=freq)

    if not isinstance(values, PeriodArray):
        raise TypeError("PeriodIndex._simple_new only accepts PeriodArray")
    result = object.__new__(cls)
    result._data = values
    result.name = name
    result._reset_identity()
    return result