Skip to content

Commit cc2bfc8

Browse files
committed
Merge remote-tracking branch 'upstream/master' into ea-divmod
2 parents 11a0d93 + fe67b94 commit cc2bfc8

30 files changed

+285
-209
lines changed

.travis.yml

+7-12
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,20 @@ matrix:
5353
- dist: trusty
5454
env:
5555
- JOB="3.6, coverage" ENV_FILE="ci/travis-36.yaml" TEST_ARGS="--skip-slow --skip-network" PANDAS_TESTING_MODE="deprecate" COVERAGE=true DOCTEST=true
56-
# In allow_failures
57-
- dist: trusty
58-
env:
59-
- JOB="3.6, slow" ENV_FILE="ci/travis-36-slow.yaml" SLOW=true
60-
# In allow_failures
56+
6157
- dist: trusty
6258
env:
6359
- JOB="3.7, NumPy dev" ENV_FILE="ci/travis-37-numpydev.yaml" TEST_ARGS="--skip-slow --skip-network -W error" PANDAS_TESTING_MODE="deprecate"
6460
addons:
6561
apt:
6662
packages:
6763
- xsel
64+
65+
# In allow_failures
66+
- dist: trusty
67+
env:
68+
- JOB="3.6, slow" ENV_FILE="ci/travis-36-slow.yaml" SLOW=true
69+
6870
# In allow_failures
6971
- dist: trusty
7072
env:
@@ -73,13 +75,6 @@ matrix:
7375
- dist: trusty
7476
env:
7577
- JOB="3.6, slow" ENV_FILE="ci/travis-36-slow.yaml" SLOW=true
76-
- dist: trusty
77-
env:
78-
- JOB="3.7, NumPy dev" ENV_FILE="ci/travis-37-numpydev.yaml" TEST_ARGS="--skip-slow --skip-network -W error" PANDAS_TESTING_MODE="deprecate"
79-
addons:
80-
apt:
81-
packages:
82-
- xsel
8378
- dist: trusty
8479
env:
8580
- JOB="3.6, doc" ENV_FILE="ci/travis-36-doc.yaml" DOC=true

asv_bench/benchmarks/indexing.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
import numpy as np
44
import pandas.util.testing as tm
5-
from pandas import (Series, DataFrame, MultiIndex, Int64Index, Float64Index,
6-
IntervalIndex, CategoricalIndex,
7-
IndexSlice, concat, date_range)
8-
from .pandas_vb_common import setup, Panel # noqa
5+
from pandas import (Series, DataFrame, MultiIndex, Panel,
6+
Int64Index, Float64Index, IntervalIndex,
7+
CategoricalIndex, IndexSlice, concat, date_range)
8+
from .pandas_vb_common import setup # noqa
99

1010

1111
class NumericSeriesIndexing(object):

asv_bench/benchmarks/join_merge.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33

44
import numpy as np
55
import pandas.util.testing as tm
6-
from pandas import (DataFrame, Series, MultiIndex, date_range, concat, merge,
7-
merge_asof)
6+
from pandas import (DataFrame, Series, Panel, MultiIndex,
7+
date_range, concat, merge, merge_asof)
8+
89
try:
910
from pandas import merge_ordered
1011
except ImportError:
1112
from pandas import ordered_merge as merge_ordered
1213

13-
from .pandas_vb_common import Panel, setup # noqa
14+
from .pandas_vb_common import setup # noqa
1415

1516

1617
class Append(object):

asv_bench/benchmarks/panel_ctor.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import warnings
22
from datetime import datetime, timedelta
33

4-
from pandas import DataFrame, DatetimeIndex, date_range
4+
from pandas import DataFrame, Panel, DatetimeIndex, date_range
55

6-
from .pandas_vb_common import Panel, setup # noqa
6+
from .pandas_vb_common import setup # noqa
77

88

99
class DifferentIndexes(object):

asv_bench/benchmarks/panel_methods.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import warnings
22

33
import numpy as np
4+
from pandas import Panel
45

5-
from .pandas_vb_common import Panel, setup # noqa
6+
from .pandas_vb_common import setup # noqa
67

78

89
class PanelMethods(object):

doc/source/whatsnew/v0.24.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ ExtensionType Changes
505505
- :meth:`Series.astype` and :meth:`DataFrame.astype` now dispatch to :meth:`ExtensionArray.astype` (:issue:`21185:`).
506506
- 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`)
507507
- Added :meth:`pandas.api.types.register_extension_dtype` to register an extension type with pandas (:issue:`22664`)
508+
- Updated the ``.type`` attribute for ``PeriodDtype``, ``DatetimeTZDtype``, and ``IntervalDtype`` to be instances of the dtype (``Period``, ``Timestamp``, and ``Interval`` respectively) (:issue:`22938`)
508509

509510
.. _whatsnew_0240.api.incompatibilities:
510511

pandas/core/arrays/base.py

+27-16
Original file line numberDiff line numberDiff line change
@@ -739,14 +739,22 @@ def _create_method(cls, op, coerce_to_dtype=True):
739739
----------
740740
op : function
741741
An operator that takes arguments op(a, b)
742-
coerce_to_dtype : bool
742+
coerce_to_dtype : bool, default True
743743
boolean indicating whether to attempt to convert
744-
the result to the underlying ExtensionArray dtype
745-
(default True)
744+
the result to the underlying ExtensionArray dtype.
745+
If it's not possible to create a new ExtensionArray with the
746+
values, an ndarray is returned instead.
746747
747748
Returns
748749
-------
749-
A method that can be bound to a method of a class
750+
Callable[[Any, Any], Union[ndarray, ExtensionArray]]
751+
A method that can be bound to a class. When used, the method
752+
receives the two arguments, one of which is the instance of
753+
this class, and should return an ExtensionArray or an ndarray.
754+
755+
Returning an ndarray may be necessary when the result of the
756+
`op` cannot be stored in the ExtensionArray. The dtype of the
757+
ndarray uses NumPy's normal inference rules.
750758
751759
Example
752760
-------
@@ -757,7 +765,6 @@ def _create_method(cls, op, coerce_to_dtype=True):
757765
in the class definition of MyExtensionArray to create the operator
758766
for addition, that will be based on the operator implementation
759767
of the underlying elements of the ExtensionArray
760-
761768
"""
762769

763770
def _binop(self, other):
@@ -774,20 +781,24 @@ def convert_values(param):
774781
# a TypeError should be raised
775782
res = [op(a, b) for (a, b) in zip(lvalues, rvalues)]
776783

777-
if coerce_to_dtype:
778-
if op.__name__ in {'divmod', 'rdivmod'}:
784+
def _maybe_convert(arr):
785+
if coerce_to_dtype:
786+
# https://github.com/pandas-dev/pandas/issues/22850
787+
# We catch all regular exceptions here, and fall back
788+
# to an ndarray.
779789
try:
780-
a, b = zip(*res)
781-
res = (self._from_sequence(a),
782-
self._from_sequence(b))
783-
except TypeError:
784-
pass
790+
res = self._from_sequnce(arr)
791+
except Exception:
792+
res = np.asarray(arr)
785793
else:
786-
try:
787-
res = self._from_sequence(res)
788-
except TypeError:
789-
pass
794+
res = np.asarray(arr)
795+
return res
790796

797+
if op.__name__ in {'divmod', 'rdivmod'}:
798+
a, b = zip(*res)
799+
res = _maybe_convert(a), _maybe_convert(b)
800+
else:
801+
res = _maybe_convert(res)
791802
return res
792803

793804
op_name = ops._get_op_name(op, True)

pandas/core/dtypes/base.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import numpy as np
33

44
from pandas import compat
5+
from pandas.core.dtypes.generic import ABCSeries, ABCIndexClass, ABCDataFrame
56
from pandas.errors import AbstractMethodError
67

78

@@ -83,7 +84,12 @@ def is_dtype(cls, dtype):
8384
"""
8485
dtype = getattr(dtype, 'dtype', dtype)
8586

86-
if isinstance(dtype, np.dtype):
87+
if isinstance(dtype, (ABCSeries, ABCIndexClass,
88+
ABCDataFrame, np.dtype)):
89+
# https://github.com/pandas-dev/pandas/issues/22960
90+
# avoid passing data to `construct_from_string`. This could
91+
# cause a FutureWarning from numpy about failing elementwise
92+
# comparison from, e.g., comparing DataFrame == 'category'.
8793
return False
8894
elif dtype is None:
8995
return False
@@ -175,7 +181,9 @@ def type(self):
175181
"""The scalar type for the array, e.g. ``int``
176182
177183
It's expected ``ExtensionArray[item]`` returns an instance
178-
of ``ExtensionDtype.type`` for scalar ``item``.
184+
of ``ExtensionDtype.type`` for scalar ``item``, assuming
185+
that value is valid (not NA). NA values do not need to be
186+
instances of `type`.
179187
"""
180188
raise AbstractMethodError(self)
181189

pandas/core/dtypes/common.py

+10-9
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
from pandas.compat import (string_types, text_type, binary_type,
55
PY3, PY36)
66
from pandas._libs import algos, lib
7-
from pandas._libs.tslibs import conversion
7+
from pandas._libs.tslibs import conversion, Period, Timestamp
8+
from pandas._libs.interval import Interval
89

910
from pandas.core.dtypes.dtypes import (
1011
registry, CategoricalDtype, CategoricalDtypeType, DatetimeTZDtype,
11-
DatetimeTZDtypeType, PeriodDtype, PeriodDtypeType, IntervalDtype,
12-
IntervalDtypeType, PandasExtensionDtype, ExtensionDtype,
12+
PeriodDtype, IntervalDtype,
13+
PandasExtensionDtype, ExtensionDtype,
1314
_pandas_registry)
1415
from pandas.core.dtypes.generic import (
1516
ABCCategorical, ABCPeriodIndex, ABCDatetimeIndex, ABCSeries,
@@ -1905,20 +1906,20 @@ def _get_dtype_type(arr_or_dtype):
19051906
elif isinstance(arr_or_dtype, CategoricalDtype):
19061907
return CategoricalDtypeType
19071908
elif isinstance(arr_or_dtype, DatetimeTZDtype):
1908-
return DatetimeTZDtypeType
1909+
return Timestamp
19091910
elif isinstance(arr_or_dtype, IntervalDtype):
1910-
return IntervalDtypeType
1911+
return Interval
19111912
elif isinstance(arr_or_dtype, PeriodDtype):
1912-
return PeriodDtypeType
1913+
return Period
19131914
elif isinstance(arr_or_dtype, string_types):
19141915
if is_categorical_dtype(arr_or_dtype):
19151916
return CategoricalDtypeType
19161917
elif is_datetime64tz_dtype(arr_or_dtype):
1917-
return DatetimeTZDtypeType
1918+
return Timestamp
19181919
elif is_period_dtype(arr_or_dtype):
1919-
return PeriodDtypeType
1920+
return Period
19201921
elif is_interval_dtype(arr_or_dtype):
1921-
return IntervalDtypeType
1922+
return Interval
19221923
return _get_dtype_type(np.dtype(arr_or_dtype))
19231924
try:
19241925
return arr_or_dtype.dtype.type

pandas/core/dtypes/dtypes.py

+10-26
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import numpy as np
55
from pandas import compat
66
from pandas.core.dtypes.generic import ABCIndexClass, ABCCategoricalIndex
7+
from pandas._libs.tslibs import Period, NaT, Timestamp
8+
from pandas._libs.interval import Interval
79

810
from .base import ExtensionDtype, _DtypeOpsMixin
911

@@ -469,13 +471,6 @@ def _is_boolean(self):
469471
return is_bool_dtype(self.categories)
470472

471473

472-
class DatetimeTZDtypeType(type):
473-
"""
474-
the type of DatetimeTZDtype, this metaclass determines subclass ability
475-
"""
476-
pass
477-
478-
479474
class DatetimeTZDtype(PandasExtensionDtype):
480475

481476
"""
@@ -485,7 +480,7 @@ class DatetimeTZDtype(PandasExtensionDtype):
485480
THIS IS NOT A REAL NUMPY DTYPE, but essentially a sub-class of
486481
np.datetime64[ns]
487482
"""
488-
type = DatetimeTZDtypeType
483+
type = Timestamp
489484
kind = 'M'
490485
str = '|M8[ns]'
491486
num = 101
@@ -583,20 +578,13 @@ def __eq__(self, other):
583578
str(self.tz) == str(other.tz))
584579

585580

586-
class PeriodDtypeType(type):
587-
"""
588-
the type of PeriodDtype, this metaclass determines subclass ability
589-
"""
590-
pass
591-
592-
593581
class PeriodDtype(PandasExtensionDtype):
594582
"""
595583
A Period duck-typed class, suitable for holding a period with freq dtype.
596584
597585
THIS IS NOT A REAL NUMPY DTYPE, but essentially a sub-class of np.int64.
598586
"""
599-
type = PeriodDtypeType
587+
type = Period
600588
kind = 'O'
601589
str = '|O08'
602590
base = np.dtype('O')
@@ -666,11 +654,15 @@ def construct_from_string(cls, string):
666654
raise TypeError("could not construct PeriodDtype")
667655

668656
def __unicode__(self):
669-
return "period[{freq}]".format(freq=self.freq.freqstr)
657+
return compat.text_type(self.name)
670658

671659
@property
672660
def name(self):
673-
return str(self)
661+
return str("period[{freq}]".format(freq=self.freq.freqstr))
662+
663+
@property
664+
def na_value(self):
665+
return NaT
674666

675667
def __hash__(self):
676668
# make myself hashable
@@ -705,13 +697,6 @@ def is_dtype(cls, dtype):
705697
return super(PeriodDtype, cls).is_dtype(dtype)
706698

707699

708-
class IntervalDtypeType(type):
709-
"""
710-
the type of IntervalDtype, this metaclass determines subclass ability
711-
"""
712-
pass
713-
714-
715700
@register_extension_dtype
716701
class IntervalDtype(PandasExtensionDtype, ExtensionDtype):
717702
"""
@@ -800,7 +785,6 @@ def construct_from_string(cls, string):
800785

801786
@property
802787
def type(self):
803-
from pandas import Interval
804788
return Interval
805789

806790
def __unicode__(self):

pandas/core/frame.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4908,7 +4908,8 @@ def _combine_match_index(self, other, func, level=None):
49084908
return ops.dispatch_to_series(left, right, func)
49094909
else:
49104910
# fastpath --> operate directly on values
4911-
new_data = func(left.values.T, right.values).T
4911+
with np.errstate(all="ignore"):
4912+
new_data = func(left.values.T, right.values).T
49124913
return self._constructor(new_data,
49134914
index=left.index, columns=self.columns,
49144915
copy=False)

pandas/core/indexes/base.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ def _shallow_copy(self, values=None, **kwargs):
530530

531531
return self._simple_new(values, **attributes)
532532

533-
def _shallow_copy_with_infer(self, values=None, **kwargs):
533+
def _shallow_copy_with_infer(self, values, **kwargs):
534534
"""
535535
create a new Index inferring the class with passed value, don't copy
536536
the data, use the same object attributes with passed in attributes
@@ -543,8 +543,6 @@ def _shallow_copy_with_infer(self, values=None, **kwargs):
543543
values : the values to create the new Index, optional
544544
kwargs : updates the default attributes for this Index
545545
"""
546-
if values is None:
547-
values = self.values
548546
attributes = self._get_attributes_dict()
549547
attributes.update(kwargs)
550548
attributes['copy'] = False

pandas/core/indexes/multi.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ def view(self, cls=None):
556556
result._id = self._id
557557
return result
558558

559-
def _shallow_copy_with_infer(self, values=None, **kwargs):
559+
def _shallow_copy_with_infer(self, values, **kwargs):
560560
# On equal MultiIndexes the difference is empty.
561561
# Therefore, an empty MultiIndex is returned GH13490
562562
if len(values) == 0:

pandas/core/indexes/period.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ def _from_ordinals(cls, values, name=None, freq=None, **kwargs):
287287
result._reset_identity()
288288
return result
289289

290-
def _shallow_copy_with_infer(self, values=None, **kwargs):
290+
def _shallow_copy_with_infer(self, values, **kwargs):
291291
""" we always want to return a PeriodIndex """
292292
return self._shallow_copy(values=values, **kwargs)
293293

0 commit comments

Comments
 (0)