From 1577b0ee4e59c0f767a7b2923dbc5ccfe56434a3 Mon Sep 17 00:00:00 2001 From: MeeseeksMachine <39504233+meeseeksmachine@users.noreply.github.com> Date: Thu, 7 Mar 2019 07:36:00 -0800 Subject: [PATCH] Backport PR #25556: BUG: Handle readonly arrays in period_array (#25591) --- doc/source/whatsnew/v0.24.2.rst | 1 + pandas/_libs/tslibs/period.pyx | 8 ++++++-- pandas/tests/arrays/test_period.py | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.24.2.rst b/doc/source/whatsnew/v0.24.2.rst index 4ca9d57f3a2e5..7da99590d5a0a 100644 --- a/doc/source/whatsnew/v0.24.2.rst +++ b/doc/source/whatsnew/v0.24.2.rst @@ -29,6 +29,7 @@ Fixed Regressions - Fixed regression in subtraction between :class:`Series` objects with ``datetime64[ns]`` dtype incorrectly raising ``OverflowError`` when the ``Series`` on the right contains null values (:issue:`25317`) - Fixed regression in :class:`TimedeltaIndex` where ``np.sum(index)`` incorrectly returned a zero-dimensional object instead of a scalar (:issue:`25282`) - Fixed regression in ``IntervalDtype`` construction where passing an incorrect string with 'Interval' as a prefix could result in a ``RecursionError``. (:issue:`25338`) +- Fixed regression in creating a period-dtype array from a read-only NumPy array of period objects. (:issue:`25403`) - Fixed regression in :class:`Categorical`, where constructing it from a categorical ``Series`` and an explicit ``categories=`` that differed from that in the ``Series`` created an invalid object which could trigger segfaults. (:issue:`25318`) - Fixed pip installing from source into an environment without NumPy (:issue:`25193`) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 2f4edb7de8f95..02fae1d09fd82 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -1437,7 +1437,9 @@ cdef accessor _get_accessor_func(int code): @cython.wraparound(False) @cython.boundscheck(False) -def extract_ordinals(object[:] values, freq): +def extract_ordinals(ndarray[object] values, freq): + # TODO: Change type to const object[:] when Cython supports that. + cdef: Py_ssize_t i, n = len(values) int64_t[:] ordinals = np.empty(n, dtype=np.int64) @@ -1471,7 +1473,9 @@ def extract_ordinals(object[:] values, freq): return ordinals.base # .base to access underlying np.ndarray -def extract_freq(object[:] values): +def extract_freq(ndarray[object] values): + # TODO: Change type to const object[:] when Cython supports that. + cdef: Py_ssize_t i, n = len(values) object p diff --git a/pandas/tests/arrays/test_period.py b/pandas/tests/arrays/test_period.py index affe3b3854490..99255d819d28e 100644 --- a/pandas/tests/arrays/test_period.py +++ b/pandas/tests/arrays/test_period.py @@ -41,6 +41,22 @@ def test_period_array_ok(data, freq, expected): tm.assert_numpy_array_equal(result, expected) +def test_period_array_readonly_object(): + # https://github.com/pandas-dev/pandas/issues/25403 + pa = period_array([pd.Period('2019-01-01')]) + arr = np.asarray(pa, dtype='object') + arr.setflags(write=False) + + result = period_array(arr) + tm.assert_period_array_equal(result, pa) + + result = pd.Series(arr) + tm.assert_series_equal(result, pd.Series(pa)) + + result = pd.DataFrame({"A": arr}) + tm.assert_frame_equal(result, pd.DataFrame({"A": pa})) + + def test_from_datetime64_freq_changes(): # https://github.com/pandas-dev/pandas/issues/23438 arr = pd.date_range("2017", periods=3, freq="D")