Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,12 @@ def _formatter(self, boxed=False):
def nbytes(self):
return self._data.nbytes

def __array__(self, dtype=None):
# used for Timedelta/DatetimeArray, overwritten by PeriodArray
if is_object_dtype(dtype):
return np.array(list(self), dtype=object)
return self._data
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would raise if dtype not in [None, object]


@property
def shape(self):
return (len(self),)
Expand Down
12 changes: 2 additions & 10 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from pandas.core.dtypes.common import (
_INT64_DTYPE, _NS_DTYPE, is_categorical_dtype, is_datetime64_dtype,
is_datetime64_ns_dtype, is_datetime64tz_dtype, is_dtype_equal,
is_extension_type, is_float_dtype, is_int64_dtype, is_object_dtype,
is_period_dtype, is_string_dtype, is_timedelta64_dtype, pandas_dtype)
is_extension_type, is_float_dtype, is_object_dtype, is_period_dtype,
is_string_dtype, is_timedelta64_dtype, pandas_dtype)
from pandas.core.dtypes.dtypes import DatetimeTZDtype
from pandas.core.dtypes.generic import ABCIndexClass, ABCPandasArray, ABCSeries
from pandas.core.dtypes.missing import isna
Expand Down Expand Up @@ -521,14 +521,6 @@ def _resolution(self):
# ----------------------------------------------------------------
# Array-Like / EA-Interface Methods

def __array__(self, dtype=None):
if is_object_dtype(dtype):
return np.array(list(self), dtype=object)
elif is_int64_dtype(dtype):
return self.asi8

return self._data

def __iter__(self):
"""
Return an iterator over the boxed values
Expand Down
4 changes: 4 additions & 0 deletions pandas/core/arrays/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@ def freq(self):
"""
return self.dtype.freq

def __array__(self, dtype=None):
# overriding DatetimelikeArray
return np.array(list(self), dtype=object)

# --------------------------------------------------------------------
# Vectorized analogues of Period properties

Expand Down
12 changes: 1 addition & 11 deletions pandas/core/arrays/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

from pandas.core.dtypes.common import (
_NS_DTYPE, _TD_DTYPE, ensure_int64, is_datetime64_dtype, is_float_dtype,
is_int64_dtype, is_integer_dtype, is_list_like, is_object_dtype, is_scalar,
is_integer_dtype, is_list_like, is_object_dtype, is_scalar,
is_string_dtype, is_timedelta64_dtype, is_timedelta64_ns_dtype,
pandas_dtype)
from pandas.core.dtypes.dtypes import DatetimeTZDtype
Expand Down Expand Up @@ -263,16 +263,6 @@ def _maybe_clear_freq(self):
# ----------------------------------------------------------------
# Array-Like / EA-Interface Methods

def __array__(self, dtype=None):
# TODO(https://github.com/pandas-dev/pandas/pull/23593)
# Maybe push to parent once datetimetz __array__ is figured out.
if is_object_dtype(dtype):
return np.array(list(self), dtype=object)
elif is_int64_dtype(dtype):
return self.asi8

return self._data

@Appender(dtl.DatetimeLikeArrayMixin._validate_fill_value.__doc__)
def _validate_fill_value(self, fill_value):
if isna(fill_value):
Expand Down
77 changes: 72 additions & 5 deletions pandas/tests/arrays/test_datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,26 @@ def test_array_object_dtype(self, tz_naive_fixture):
result = np.array(dti, dtype=object)
tm.assert_numpy_array_equal(result, expected)

def test_array(self, tz_naive_fixture):
def test_array(self, datetime_index):
arr = DatetimeArray(datetime_index)

result = np.asarray(arr)
expected = arr._data
assert result is expected
tm.assert_numpy_array_equal(result, expected)

result = np.asarray(arr, dtype=object)
expected = np.array(list(arr), dtype=object)
tm.assert_numpy_array_equal(result, expected)

# to other dtype always copies
result = np.asarray(arr, dtype='int64')
assert result is not arr.asi8
assert not np.may_share_memory(arr, result)
expected = arr.asi8.copy()
tm.assert_numpy_array_equal(result, expected)

def test_array_tz(self, tz_naive_fixture):
# GH#23524
tz = tz_naive_fixture
dti = pd.date_range('2016-01-01', periods=3, tz=tz)
Expand All @@ -273,7 +292,6 @@ def test_array(self, tz_naive_fixture):
assert result.base is not None

def test_array_i8_dtype(self, tz_naive_fixture):
# GH#23524
tz = tz_naive_fixture
dti = pd.date_range('2016-01-01', periods=3, tz=tz)
arr = DatetimeArray(dti)
Expand All @@ -285,10 +303,10 @@ def test_array_i8_dtype(self, tz_naive_fixture):
result = np.array(arr, dtype=np.int64)
tm.assert_numpy_array_equal(result, expected)

# check that we are not making copies when setting copy=False
# check that we are still making copies when setting copy=False
result = np.array(arr, dtype='i8', copy=False)
assert result.base is expected.base
assert result.base is not None
assert result.base is not expected.base
assert result.base is None

def test_from_array_keeps_base(self):
# Ensure that DatetimeArray._data.base isn't lost.
Expand Down Expand Up @@ -468,6 +486,35 @@ def test_int_properties(self, timedelta_index, propname):

tm.assert_numpy_array_equal(result, expected)

def test_array(self, timedelta_index):
arr = TimedeltaArray(timedelta_index)

result = np.asarray(arr)
expected = arr._data
assert result is expected
tm.assert_numpy_array_equal(result, expected)
result = np.array(arr, copy=False)
assert result is expected
tm.assert_numpy_array_equal(result, expected)

# to object dtype
result = np.asarray(arr, dtype=object)
expected = np.array(list(arr), dtype=object)
tm.assert_numpy_array_equal(result, expected)

# to other dtype always copies
result = np.asarray(arr, dtype='int64')
assert result is not arr.asi8
assert not np.may_share_memory(arr, result)
expected = arr.asi8.copy()
tm.assert_numpy_array_equal(result, expected)

# other dtypes handled by numpy
for dtype in ['float64', str]:
result = np.asarray(arr, dtype=dtype)
expected = np.asarray(arr).astype(dtype)
tm.assert_numpy_array_equal(result, expected)

def test_take_fill_valid(self, timedelta_index):
tdi = timedelta_index
arr = TimedeltaArray(tdi)
Expand Down Expand Up @@ -541,3 +588,23 @@ def test_int_properties(self, period_index, propname):
expected = np.array(getattr(pi, propname))

tm.assert_numpy_array_equal(result, expected)

def test_array(self, period_index):
arr = PeriodArray(period_index)

result = np.asarray(arr)
expected = np.array(list(arr), dtype=object)
tm.assert_numpy_array_equal(result, expected)

result = np.asarray(arr, dtype=object)
tm.assert_numpy_array_equal(result, expected)

with pytest.raises(TypeError):
np.asarray(arr, dtype='int64')

with pytest.raises(TypeError):
np.asarray(arr, dtype='float64')

result = np.asarray(arr, dtype='S20')
expected = np.asarray(arr).astype('S20')
tm.assert_numpy_array_equal(result, expected)
5 changes: 5 additions & 0 deletions pandas/tests/extension/base/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pandas.core.dtypes.dtypes import ExtensionDtype

import pandas as pd
import pandas.util.testing as tm

from .base import BaseExtensionTests

Expand Down Expand Up @@ -33,6 +34,10 @@ def test_array_interface(self, data):
result = np.array(data)
assert result[0] == data[0]

result = np.array(data, dtype=object)
expected = np.array(list(data), dtype=object)
tm.assert_numpy_array_equal(result, expected)

def test_is_extension_array_dtype(self, data):
assert is_extension_array_dtype(data)
assert is_extension_array_dtype(data.dtype)
Expand Down