From 043905982699ef7b276bcd151169b9d8dc7575f6 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Wed, 9 Jan 2019 10:33:38 -0800 Subject: [PATCH 1/4] do freq validation in DTA.__init__ --- pandas/core/arrays/datetimes.py | 17 +++++++++++++++-- pandas/tests/arrays/test_datetimes.py | 10 ++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index efa1757a989fc..d2d9fcf954fe3 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -258,6 +258,8 @@ def __init__(self, values, dtype=_NS_DTYPE, freq=None, copy=False): if isinstance(values, (ABCSeries, ABCIndexClass)): values = values._values + inferred_freq = getattr(values, "_freq", None) + if isinstance(values, type(self)): # validation dtz = getattr(dtype, 'tz', None) @@ -322,9 +324,20 @@ def __init__(self, values, dtype=_NS_DTYPE, freq=None, copy=False): self._dtype = dtype self._freq = freq + if inferred_freq is None and freq is not None: + type(self)._validate_frequency(self, freq) + @classmethod - def _simple_new(cls, values, freq=None, dtype=None): - return cls(values, freq=freq, dtype=dtype) + def _simple_new(cls, values, freq=None, dtype=_NS_DTYPE): + assert isinstance(values, np.ndarray) + if values.dtype == 'i8': + values = values.view(_NS_DTYPE) + + result = object.__new__(cls) + result._data = values + result._freq = freq + result._dtype = dtype + return result @classmethod def _from_sequence(cls, data, dtype=None, copy=False, diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py index 8228ed7652fea..60caf61782bbf 100644 --- a/pandas/tests/arrays/test_datetimes.py +++ b/pandas/tests/arrays/test_datetimes.py @@ -16,6 +16,16 @@ class TestDatetimeArrayConstructor(object): + def test_freq_validation(self): + # GH#24623 check that invalid instances cannot be created with the + # public constructor + arr = np.arange(5, dtype=np.int64) * 3600 * 10**9 + + msg = ("Inferred frequency H from passed values does not " + "conform to passed frequency W-SUN") + with pytest.raises(ValueError, match=msg): + DatetimeArray(arr, freq="W") + @pytest.mark.parametrize('meth', [DatetimeArray._from_sequence, sequence_to_dt64ns, pd.to_datetime, From 2e1b62577bc66cf0bf916859f6f325370b87c898 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Wed, 9 Jan 2019 11:56:44 -0800 Subject: [PATCH 2/4] troubleshoot parquet fail --- pandas/core/internals/blocks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 70e4f44cb5de8..50a935a92bf5c 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -3078,7 +3078,7 @@ def make_block(values, placement, klass=None, ndim=None, dtype=None, elif klass is DatetimeTZBlock and not is_datetime64tz_dtype(values): # TODO: This is no longer hit internally; does it need to be retained # for e.g. pyarrow? - values = DatetimeArray(values, dtype) + values = DatetimeArray._simple_new(values, dtype) return klass(values, ndim=ndim, placement=placement) From da92cea260b705efc5a386585e0c791387037b96 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Wed, 9 Jan 2019 12:38:01 -0800 Subject: [PATCH 3/4] troubleshoot feather --- pandas/core/internals/blocks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 50a935a92bf5c..15e8321c0c7f8 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -3078,7 +3078,7 @@ def make_block(values, placement, klass=None, ndim=None, dtype=None, elif klass is DatetimeTZBlock and not is_datetime64tz_dtype(values): # TODO: This is no longer hit internally; does it need to be retained # for e.g. pyarrow? - values = DatetimeArray._simple_new(values, dtype) + values = DatetimeArray._simple_new(values, dtype=dtype) return klass(values, ndim=ndim, placement=placement) From f63e32d6cf68b5e1ddc9a3c03dfeb3763e54c289 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Wed, 9 Jan 2019 14:35:05 -0800 Subject: [PATCH 4/4] troubleshoot pyarrow fail --- pandas/core/arrays/datetimelike.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index cfb697b3c357a..73e799f9e0a36 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -606,7 +606,7 @@ def _concat_same_type(cls, to_concat): def copy(self, deep=False): values = self.asi8.copy() - return type(self)(values, dtype=self.dtype, freq=self.freq) + return type(self)._simple_new(values, dtype=self.dtype, freq=self.freq) def _values_for_factorize(self): return self.asi8, iNaT