Skip to content

Commit

Permalink
Update type for PeriodDtype / DatetimeTZDtype / IntervalDtype (#22938)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAugspurger authored and jreback committed Oct 4, 2018
1 parent b12e5ba commit fe67b94
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 42 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.24.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ ExtensionType Changes
- :meth:`Series.astype` and :meth:`DataFrame.astype` now dispatch to :meth:`ExtensionArray.astype` (:issue:`21185:`).
- Slicing a single row of a ``DataFrame`` with multiple ExtensionArrays of the same type now preserves the dtype, rather than coercing to object (:issue:`22784`)
- Added :meth:`pandas.api.types.register_extension_dtype` to register an extension type with pandas (:issue:`22664`)
- Updated the ``.type`` attribute for ``PeriodDtype``, ``DatetimeTZDtype``, and ``IntervalDtype`` to be instances of the dtype (``Period``, ``Timestamp``, and ``Interval`` respectively) (:issue:`22938`)

.. _whatsnew_0240.api.incompatibilities:

Expand Down
4 changes: 3 additions & 1 deletion pandas/core/dtypes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,9 @@ def type(self):
"""The scalar type for the array, e.g. ``int``
It's expected ``ExtensionArray[item]`` returns an instance
of ``ExtensionDtype.type`` for scalar ``item``.
of ``ExtensionDtype.type`` for scalar ``item``, assuming
that value is valid (not NA). NA values do not need to be
instances of `type`.
"""
raise AbstractMethodError(self)

Expand Down
19 changes: 10 additions & 9 deletions pandas/core/dtypes/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
from pandas.compat import (string_types, text_type, binary_type,
PY3, PY36)
from pandas._libs import algos, lib
from pandas._libs.tslibs import conversion
from pandas._libs.tslibs import conversion, Period, Timestamp
from pandas._libs.interval import Interval

from pandas.core.dtypes.dtypes import (
registry, CategoricalDtype, CategoricalDtypeType, DatetimeTZDtype,
DatetimeTZDtypeType, PeriodDtype, PeriodDtypeType, IntervalDtype,
IntervalDtypeType, PandasExtensionDtype, ExtensionDtype,
PeriodDtype, IntervalDtype,
PandasExtensionDtype, ExtensionDtype,
_pandas_registry)
from pandas.core.dtypes.generic import (
ABCCategorical, ABCPeriodIndex, ABCDatetimeIndex, ABCSeries,
Expand Down Expand Up @@ -1905,20 +1906,20 @@ def _get_dtype_type(arr_or_dtype):
elif isinstance(arr_or_dtype, CategoricalDtype):
return CategoricalDtypeType
elif isinstance(arr_or_dtype, DatetimeTZDtype):
return DatetimeTZDtypeType
return Timestamp
elif isinstance(arr_or_dtype, IntervalDtype):
return IntervalDtypeType
return Interval
elif isinstance(arr_or_dtype, PeriodDtype):
return PeriodDtypeType
return Period
elif isinstance(arr_or_dtype, string_types):
if is_categorical_dtype(arr_or_dtype):
return CategoricalDtypeType
elif is_datetime64tz_dtype(arr_or_dtype):
return DatetimeTZDtypeType
return Timestamp
elif is_period_dtype(arr_or_dtype):
return PeriodDtypeType
return Period
elif is_interval_dtype(arr_or_dtype):
return IntervalDtypeType
return Interval
return _get_dtype_type(np.dtype(arr_or_dtype))
try:
return arr_or_dtype.dtype.type
Expand Down
36 changes: 10 additions & 26 deletions pandas/core/dtypes/dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import numpy as np
from pandas import compat
from pandas.core.dtypes.generic import ABCIndexClass, ABCCategoricalIndex
from pandas._libs.tslibs import Period, NaT, Timestamp
from pandas._libs.interval import Interval

from .base import ExtensionDtype, _DtypeOpsMixin

Expand Down Expand Up @@ -469,13 +471,6 @@ def _is_boolean(self):
return is_bool_dtype(self.categories)


class DatetimeTZDtypeType(type):
"""
the type of DatetimeTZDtype, this metaclass determines subclass ability
"""
pass


class DatetimeTZDtype(PandasExtensionDtype):

"""
Expand All @@ -485,7 +480,7 @@ class DatetimeTZDtype(PandasExtensionDtype):
THIS IS NOT A REAL NUMPY DTYPE, but essentially a sub-class of
np.datetime64[ns]
"""
type = DatetimeTZDtypeType
type = Timestamp
kind = 'M'
str = '|M8[ns]'
num = 101
Expand Down Expand Up @@ -583,20 +578,13 @@ def __eq__(self, other):
str(self.tz) == str(other.tz))


class PeriodDtypeType(type):
"""
the type of PeriodDtype, this metaclass determines subclass ability
"""
pass


class PeriodDtype(PandasExtensionDtype):
"""
A Period duck-typed class, suitable for holding a period with freq dtype.
THIS IS NOT A REAL NUMPY DTYPE, but essentially a sub-class of np.int64.
"""
type = PeriodDtypeType
type = Period
kind = 'O'
str = '|O08'
base = np.dtype('O')
Expand Down Expand Up @@ -666,11 +654,15 @@ def construct_from_string(cls, string):
raise TypeError("could not construct PeriodDtype")

def __unicode__(self):
return "period[{freq}]".format(freq=self.freq.freqstr)
return compat.text_type(self.name)

@property
def name(self):
return str(self)
return str("period[{freq}]".format(freq=self.freq.freqstr))

@property
def na_value(self):
return NaT

def __hash__(self):
# make myself hashable
Expand Down Expand Up @@ -705,13 +697,6 @@ def is_dtype(cls, dtype):
return super(PeriodDtype, cls).is_dtype(dtype)


class IntervalDtypeType(type):
"""
the type of IntervalDtype, this metaclass determines subclass ability
"""
pass


@register_extension_dtype
class IntervalDtype(PandasExtensionDtype, ExtensionDtype):
"""
Expand Down Expand Up @@ -800,7 +785,6 @@ def construct_from_string(cls, string):

@property
def type(self):
from pandas import Interval
return Interval

def __unicode__(self):
Expand Down
12 changes: 6 additions & 6 deletions pandas/tests/dtypes/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,15 +605,15 @@ def test__get_dtype_fails(input_param):
(pd.DatetimeIndex([1, 2]), np.datetime64),
(pd.DatetimeIndex([1, 2]).dtype, np.datetime64),
('<M8[ns]', np.datetime64),
(pd.DatetimeIndex([1, 2], tz='Europe/London'), com.DatetimeTZDtypeType),
(pd.DatetimeIndex([1, 2], tz='Europe/London'), pd.Timestamp),
(pd.DatetimeIndex([1, 2], tz='Europe/London').dtype,
com.DatetimeTZDtypeType),
('datetime64[ns, Europe/London]', com.DatetimeTZDtypeType),
pd.Timestamp),
('datetime64[ns, Europe/London]', pd.Timestamp),
(pd.SparseSeries([1, 2], dtype='int32'), np.int32),
(pd.SparseSeries([1, 2], dtype='int32').dtype, np.int32),
(PeriodDtype(freq='D'), com.PeriodDtypeType),
('period[D]', com.PeriodDtypeType),
(IntervalDtype(), com.IntervalDtypeType),
(PeriodDtype(freq='D'), pd.Period),
('period[D]', pd.Period),
(IntervalDtype(), pd.Interval),
(None, type(None)),
(1, type(None)),
(1.2, type(None)),
Expand Down

0 comments on commit fe67b94

Please sign in to comment.