From e89d18c81b5ca74425f63b189d52b656b963b377 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Tue, 14 Nov 2023 13:00:53 -0800 Subject: [PATCH] BUG: PeriodIndex.__new__ with keyword mismatch (#55961) * BUG: PeriodIndex.__new__ with keyword mismatch * GH refs --- doc/source/whatsnew/v2.2.0.rst | 1 + pandas/core/indexes/period.py | 8 +++++++- pandas/tests/indexes/period/test_constructors.py | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index c6f03c0000176..9040dba238c88 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -420,6 +420,7 @@ I/O Period ^^^^^^ +- Bug in :class:`PeriodIndex` construction when more than one of ``data``, ``ordinal`` and ``**fields`` are passed failing to raise ``ValueError`` (:issue:`55961`) - Bug in :class:`Period` addition silently wrapping around instead of raising ``OverflowError`` (:issue:`55503`) - Bug in casting from :class:`PeriodDtype` with ``astype`` to ``datetime64`` or :class:`DatetimeTZDtype` with non-nanosecond unit incorrectly returning with nanosecond unit (:issue:`55958`) - diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index 09b41d9c32ec2..faf058eff4bf4 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -249,6 +249,11 @@ def __new__( dtype = PeriodDtype(freq) data = PeriodArray(data, dtype=dtype) + elif fields: + if data is not None: + raise ValueError("Cannot pass both data and fields") + raise ValueError("Cannot pass both ordinal and fields") + else: freq = validate_dtype_freq(dtype, freq) @@ -261,10 +266,11 @@ def __new__( data = data.asfreq(freq) if data is None and ordinal is not None: - # we strangely ignore `ordinal` if data is passed. ordinal = np.asarray(ordinal, dtype=np.int64) dtype = PeriodDtype(freq) data = PeriodArray(ordinal, dtype=dtype) + elif data is not None and ordinal is not None: + raise ValueError("Cannot pass both data and ordinal") else: # don't pass copy here, since we copy later. data = period_array(data=data, freq=freq) diff --git a/pandas/tests/indexes/period/test_constructors.py b/pandas/tests/indexes/period/test_constructors.py index 865bfdc725f9c..79837af79c189 100644 --- a/pandas/tests/indexes/period/test_constructors.py +++ b/pandas/tests/indexes/period/test_constructors.py @@ -20,6 +20,22 @@ class TestPeriodIndex: + def test_keyword_mismatch(self): + # GH#55961 we should get exactly one of data/ordinals/**fields + per = Period("2016-01-01", "D") + + err_msg1 = "Cannot pass both data and ordinal" + with pytest.raises(ValueError, match=err_msg1): + PeriodIndex(data=[per], ordinal=[per.ordinal], freq=per.freq) + + err_msg2 = "Cannot pass both data and fields" + with pytest.raises(ValueError, match=err_msg2): + PeriodIndex(data=[per], year=[per.year], freq=per.freq) + + err_msg3 = "Cannot pass both ordinal and fields" + with pytest.raises(ValueError, match=err_msg3): + PeriodIndex(ordinal=[per.ordinal], year=[per.year], freq=per.freq) + def test_construction_base_constructor(self): # GH 13664 arr = [Period("2011-01", freq="M"), NaT, Period("2011-03", freq="M")]