# Buggy code
def __new__(
    cls,
    data=None,
    ordinal=None,
    freq=None,
    tz=None,
    dtype=None,
    copy=False,
    name=None,
    **fields,
):
    valid_field_set = {
        "year",
        "month",
        "day",
        "quarter",
        "hour",
        "minute",
        "second",
    }

    if not set(fields).issubset(valid_field_set):
        argument = list(set(fields) - valid_field_set)[0]
        raise TypeError(f"__new__() got an unexpected keyword argument {argument}")

    if name is None and hasattr(data, "name"):
        name = data.name

    if data is None and ordinal is None:
        # range-based.
        data, freq2 = PeriodArray._generate_range(None, None, None, freq, fields)
        # PeriodArray._generate range does validation that fields is
        # empty when really using the range-based constructor.
        freq = freq2

        data = PeriodArray(data, freq=freq)
    else:
        freq = validate_dtype_freq(dtype, freq)

        # PeriodIndex allow PeriodIndex(period_index, freq=different)
        # Let's not encourage that kind of behavior in PeriodArray.

        if freq and isinstance(data, cls) and data.freq != freq:
            # TODO: We can do some of these with no-copy / coercion?
            # e.g. D -> 2D seems to be OK
            data = data.asfreq(freq)

        if data is None and ordinal is not None:
            # we strangely ignore `ordinal` if data is passed.
            ordinal = np.asarray(ordinal, dtype=np.int64)
            data = PeriodArray(ordinal, freq)
        else:
            # don't pass copy here, since we copy later.
            data = period_array(data=data, freq=freq)

    if copy:
        data = data.copy()

    return cls._simple_new(data, name=name)


# Traceback (TypeError)
In [5]: pd.Series([], name=[])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-2c73ddde103e> in <module>
----> 1 pd.Series([], name=[])

~/sandbox/pandas/pandas/core/series.py in __init__(self, data, index, dtype, name, copy, fastpath)
326         generic.NDFrame.__init__(self, data, fastpath=True)
327
--> 328         self.name = name
329         self._set_axis(0, index, fastpath=True)
330

~/sandbox/pandas/pandas/core/generic.py in __setattr__(self, name, value)
5257             object.__setattr__(self, name, value)
5258         elif name in self._metadata:
-> 5259             object.__setattr__(self, name, value)
5260         else:
5261             try:

~/sandbox/pandas/pandas/core/series.py in name(self, value)
468     def name(self, value):
469         if value is not None and not is_hashable(value):
--> 470             raise TypeError("Series.name must be a hashable type")
471         object.__setattr__(self, "_name", value)
472

TypeError: Series.name must be a hashable type

# Fixed code
def __new__(
    cls,
    data=None,
    ordinal=None,
    freq=None,
    tz=None,
    dtype=None,
    copy=False,
    name=None,
    **fields,
):
    valid_field_set = {
        "year",
        "month",
        "day",
        "quarter",
        "hour",
        "minute",
        "second",
    }

    if not set(fields).issubset(valid_field_set):
        argument = list(set(fields) - valid_field_set)[0]
        raise TypeError(f"__new__() got an unexpected keyword argument {argument}")

    name = maybe_extract_name(name, data, cls)

    if data is None and ordinal is None:
        # range-based.
        data, freq2 = PeriodArray._generate_range(None, None, None, freq, fields)
        # PeriodArray._generate range does validation that fields is
        # empty when really using the range-based constructor.
        freq = freq2

        data = PeriodArray(data, freq=freq)
    else:
        freq = validate_dtype_freq(dtype, freq)

        # PeriodIndex allow PeriodIndex(period_index, freq=different)
        # Let's not encourage that kind of behavior in PeriodArray.

        if freq and isinstance(data, cls) and data.freq != freq:
            # TODO: We can do some of these with no-copy / coercion?
            # e.g. D -> 2D seems to be OK
            data = data.asfreq(freq)

        if data is None and ordinal is not None:
            # we strangely ignore `ordinal` if data is passed.
            ordinal = np.asarray(ordinal, dtype=np.int64)
            data = PeriodArray(ordinal, freq)
        else:
            # don't pass copy here, since we copy later.
            data = period_array(data=data, freq=freq)

    if copy:
        data = data.copy()

    return cls._simple_new(data, name=name)