Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TST: de-duplicate PeriodIndex constructor tests #56435

Merged
merged 3 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
159 changes: 94 additions & 65 deletions pandas/tests/indexes/period/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,54 @@
from pandas.core.arrays import PeriodArray


class TestPeriodIndexDisallowedFreqs:
@pytest.mark.parametrize(
"freq,freq_depr",
[
("2M", "2ME"),
("2Q-MAR", "2QE-MAR"),
("2Y-FEB", "2YE-FEB"),
],
)
def test_period_index_frequency_ME_error_message(self, freq, freq_depr):
# GH#52064
msg = f"for Period, please use '{freq[1:]}' instead of '{freq_depr[1:]}'"

with pytest.raises(ValueError, match=msg):
PeriodIndex(["2020-01-01", "2020-01-02"], freq=freq_depr)

with pytest.raises(ValueError, match=msg):
period_range(start="2020-01-01", end="2020-01-02", freq=freq_depr)

@pytest.mark.parametrize("freq_depr", ["2SME", "2CBME", "2BYE"])
def test_period_index_frequency_invalid_freq(self, freq_depr):
# GH#9586
msg = f"Invalid frequency: {freq_depr[1:]}"

with pytest.raises(ValueError, match=msg):
period_range("2020-01", "2020-05", freq=freq_depr)
with pytest.raises(ValueError, match=msg):
PeriodIndex(["2020-01", "2020-05"], freq=freq_depr)


class TestPeriodIndex:
def test_from_ordinals(self):
Period(ordinal=-1000, freq="Y")
Period(ordinal=0, freq="Y")

msg = "The 'ordinal' keyword in PeriodIndex is deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
idx1 = PeriodIndex(ordinal=[-1, 0, 1], freq="Y")
with tm.assert_produces_warning(FutureWarning, match=msg):
idx2 = PeriodIndex(ordinal=np.array([-1, 0, 1]), freq="Y")
tm.assert_index_equal(idx1, idx2)

alt1 = PeriodIndex.from_ordinals([-1, 0, 1], freq="Y")
tm.assert_index_equal(alt1, idx1)

alt2 = PeriodIndex.from_ordinals(np.array([-1, 0, 1]), freq="Y")
tm.assert_index_equal(alt2, idx2)

def test_keyword_mismatch(self):
# GH#55961 we should get exactly one of data/ordinals/**fields
per = Period("2016-01-01", "D")
Expand Down Expand Up @@ -131,11 +178,6 @@ def test_constructor_field_arrays(self):
exp = period_range("2007-01", periods=3, freq="M")
tm.assert_index_equal(idx, exp)

def test_constructor_U(self):
# U was used as undefined period
with pytest.raises(ValueError, match="Invalid frequency: X"):
period_range("2007-1-1", periods=500, freq="X")

def test_constructor_nano(self):
idx = period_range(
start=Period(ordinal=1, freq="ns"),
Expand Down Expand Up @@ -371,49 +413,12 @@ def test_constructor_mixed(self):
exp = PeriodIndex(["2011-01-01", "NaT", "2012-01-01"], freq="D")
tm.assert_index_equal(idx, exp)

def test_constructor_simple_new(self):
idx = period_range("2007-01", name="p", periods=2, freq="M")

with pytest.raises(AssertionError, match="<class .*PeriodIndex'>"):
idx._simple_new(idx, name="p")

result = idx._simple_new(idx._data, name="p")
tm.assert_index_equal(result, idx)

msg = "Should be numpy array of type i8"
with pytest.raises(AssertionError, match=msg):
# Need ndarray, not int64 Index
type(idx._data)._simple_new(Index(idx.asi8), dtype=idx.dtype)

arr = type(idx._data)._simple_new(idx.asi8, dtype=idx.dtype)
result = idx._simple_new(arr, name="p")
tm.assert_index_equal(result, idx)

def test_constructor_simple_new_empty(self):
# GH13079
idx = PeriodIndex([], freq="M", name="p")
with pytest.raises(AssertionError, match="<class .*PeriodIndex'>"):
idx._simple_new(idx, name="p")

result = idx._simple_new(idx._data, name="p")
tm.assert_index_equal(result, idx)

@pytest.mark.parametrize("floats", [[1.1, 2.1], np.array([1.1, 2.1])])
def test_constructor_floats(self, floats):
with pytest.raises(AssertionError, match="<class "):
PeriodIndex._simple_new(floats)

msg = "PeriodIndex does not allow floating point in construction"
with pytest.raises(TypeError, match=msg):
PeriodIndex(floats)

def test_constructor_nat(self):
msg = "start and end must not be NaT"
with pytest.raises(ValueError, match=msg):
period_range(start="NaT", end="2011-01-01", freq="M")
with pytest.raises(ValueError, match=msg):
period_range(start="2011-01-01", end="NaT", freq="M")

def test_constructor_year_and_quarter(self):
year = Series([2001, 2002, 2003])
quarter = year - 2000
Expand Down Expand Up @@ -493,7 +498,7 @@ def test_constructor_freq_combined(self):
expected = PeriodIndex(["2016-01-01 00:00", "2016-01-02 01:00"], freq="25h")
tm.assert_index_equal(pidx, expected)

def test_constructor(self):
def test_period_range_length(self):
pi = period_range(freq="Y", start="1/1/2001", end="12/1/2009")
assert len(pi) == 9

Expand Down Expand Up @@ -539,9 +544,12 @@ def test_constructor(self):
assert (i1 == i2).all()
assert i1.freq == i2.freq

def test_infer_freq_from_first_element(self):
msg = "Period with BDay freq is deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
start = Period("02-Apr-2005", "B")
end_intv = Period("2005-05-01", "B")
i1 = period_range(start=start, end=end_intv)
period_range(start=start, end=end_intv)

# infer freq from first element
i2 = PeriodIndex([end_intv, Period("2005-05-05", "B")])
Expand All @@ -553,7 +561,12 @@ def test_constructor(self):
assert len(i2) == 2
assert i2[0] == end_intv

def test_mixed_freq_raises(self):
# Mixed freq should fail
msg = "Period with BDay freq is deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
end_intv = Period("2005-05-01", "B")

vals = [end_intv, Period("2006-12-31", "w")]
msg = r"Input has different freq=W-SUN from PeriodIndex\(freq=B\)"
with pytest.raises(IncompatibleFrequency, match=msg):
Expand All @@ -562,10 +575,6 @@ def test_constructor(self):
with pytest.raises(IncompatibleFrequency, match=msg):
PeriodIndex(vals)

# tuple freq disallowed GH#34703
with pytest.raises(TypeError, match="pass as a string instead"):
Period("2006-12-31", ("w", 1))

@pytest.mark.parametrize(
"freq", ["M", "Q", "Y", "D", "B", "min", "s", "ms", "us", "ns", "h"]
)
Expand Down Expand Up @@ -594,20 +603,39 @@ def test_map_with_string_constructor(self):
# lastly, values should compare equal
tm.assert_index_equal(res, expected)

@pytest.mark.parametrize(
"freq, freq_msg",
[
(offsets.BYearBegin(), "BYearBegin"),
(offsets.YearBegin(2), "YearBegin"),
(offsets.QuarterBegin(startingMonth=12), "QuarterBegin"),
(offsets.BusinessMonthEnd(2), "BusinessMonthEnd"),
],
)
def test_offsets_not_supported(self, freq, freq_msg):
# GH#55785
msg = f"{freq_msg} is not supported as period frequency"
with pytest.raises(TypeError, match=msg):
Period(year=2014, freq=freq)

class TestSimpleNew:
def test_constructor_simple_new(self):
idx = period_range("2007-01", name="p", periods=2, freq="M")

with pytest.raises(AssertionError, match="<class .*PeriodIndex'>"):
idx._simple_new(idx, name="p")

result = idx._simple_new(idx._data, name="p")
tm.assert_index_equal(result, idx)

msg = "Should be numpy array of type i8"
with pytest.raises(AssertionError, match=msg):
# Need ndarray, not int64 Index
type(idx._data)._simple_new(Index(idx.asi8), dtype=idx.dtype)

arr = type(idx._data)._simple_new(idx.asi8, dtype=idx.dtype)
result = idx._simple_new(arr, name="p")
tm.assert_index_equal(result, idx)

def test_constructor_simple_new_empty(self):
# GH13079
idx = PeriodIndex([], freq="M", name="p")
with pytest.raises(AssertionError, match="<class .*PeriodIndex'>"):
idx._simple_new(idx, name="p")

result = idx._simple_new(idx._data, name="p")
tm.assert_index_equal(result, idx)

@pytest.mark.parametrize("floats", [[1.1, 2.1], np.array([1.1, 2.1])])
def test_period_index_simple_new_disallows_floats(self, floats):
with pytest.raises(AssertionError, match="<class "):
PeriodIndex._simple_new(floats)


class TestShallowCopy:
Expand Down Expand Up @@ -638,6 +666,7 @@ def test_constructor_cant_cast_period(self):
Series(period_range("2000-01-01", periods=10, freq="D"), dtype=float)

def test_constructor_cast_object(self):
s = Series(period_range("1/1/2000", periods=10), dtype=PeriodDtype("D"))
exp = Series(period_range("1/1/2000", periods=10))
tm.assert_series_equal(s, exp)
pi = period_range("1/1/2000", periods=10)
ser = Series(pi, dtype=PeriodDtype("D"))
exp = Series(pi)
tm.assert_series_equal(ser, exp)
136 changes: 0 additions & 136 deletions pandas/tests/indexes/period/test_period.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import numpy as np
import pytest

from pandas._libs.tslibs.period import IncompatibleFrequency

from pandas import (
Index,
NaT,
Expand All @@ -17,11 +15,6 @@


class TestPeriodIndex:
def test_make_time_series(self):
index = period_range(freq="Y", start="1/1/2001", end="12/1/2009")
series = Series(1, index=index)
assert isinstance(series, Series)

def test_view_asi8(self):
idx = PeriodIndex([], freq="M")

Expand Down Expand Up @@ -66,74 +59,6 @@ def test_values(self):
exp = np.array([14975, -9223372036854775808], dtype=np.int64)
tm.assert_numpy_array_equal(idx.asi8, exp)

def test_period_index_length(self):
pi = period_range(freq="Y", start="1/1/2001", end="12/1/2009")
assert len(pi) == 9

pi = period_range(freq="Q", start="1/1/2001", end="12/1/2009")
assert len(pi) == 4 * 9

pi = period_range(freq="M", start="1/1/2001", end="12/1/2009")
assert len(pi) == 12 * 9

msg = "Period with BDay freq is deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
start = Period("02-Apr-2005", "B")
i1 = period_range(start=start, periods=20)
assert len(i1) == 20
assert i1.freq == start.freq
assert i1[0] == start

end_intv = Period("2006-12-31", "W")
i1 = period_range(end=end_intv, periods=10)
assert len(i1) == 10
assert i1.freq == end_intv.freq
assert i1[-1] == end_intv

end_intv = Period("2006-12-31", "1w")
i2 = period_range(end=end_intv, periods=10)
assert len(i1) == len(i2)
assert (i1 == i2).all()
assert i1.freq == i2.freq

msg = "start and end must have same freq"
msg2 = "Period with BDay freq is deprecated"
with pytest.raises(ValueError, match=msg):
with tm.assert_produces_warning(FutureWarning, match=msg2):
period_range(start=start, end=end_intv)

with tm.assert_produces_warning(FutureWarning, match=msg2):
end_intv = Period("2005-05-01", "B")
with tm.assert_produces_warning(FutureWarning, match=msg2):
i1 = period_range(start=start, end=end_intv)

msg = (
"Of the three parameters: start, end, and periods, exactly two "
"must be specified"
)
with pytest.raises(ValueError, match=msg):
period_range(start=start)

# infer freq from first element
with tm.assert_produces_warning(FutureWarning, match=msg2):
i2 = PeriodIndex([end_intv, Period("2005-05-05", "B")])
assert len(i2) == 2
assert i2[0] == end_intv

with tm.assert_produces_warning(FutureWarning, match=msg2):
i2 = PeriodIndex(np.array([end_intv, Period("2005-05-05", "B")]))
assert len(i2) == 2
assert i2[0] == end_intv

# Mixed freq should fail
vals = [end_intv, Period("2006-12-31", "w")]
msg = r"Input has different freq=W-SUN from PeriodIndex\(freq=B\)"
with pytest.raises(IncompatibleFrequency, match=msg):
PeriodIndex(vals)
vals = np.array(vals)
with pytest.raises(ValueError, match=msg):
PeriodIndex(vals)

@pytest.mark.parametrize(
"field",
[
Expand Down Expand Up @@ -210,23 +135,6 @@ def test_index_unique(self):
tm.assert_index_equal(idx.unique(), expected)
assert idx.nunique() == 3

def test_negative_ordinals(self):
Period(ordinal=-1000, freq="Y")
Period(ordinal=0, freq="Y")

msg = "The 'ordinal' keyword in PeriodIndex is deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
idx1 = PeriodIndex(ordinal=[-1, 0, 1], freq="Y")
with tm.assert_produces_warning(FutureWarning, match=msg):
idx2 = PeriodIndex(ordinal=np.array([-1, 0, 1]), freq="Y")
tm.assert_index_equal(idx1, idx2)

alt1 = PeriodIndex.from_ordinals([-1, 0, 1], freq="Y")
tm.assert_index_equal(alt1, idx1)

alt2 = PeriodIndex.from_ordinals(np.array([-1, 0, 1]), freq="Y")
tm.assert_index_equal(alt2, idx2)

def test_pindex_fieldaccessor_nat(self):
idx = PeriodIndex(
["2011-01", "2011-02", "NaT", "2012-03", "2012-04"], freq="D", name="name"
Expand Down Expand Up @@ -281,50 +189,6 @@ def test_map(self):
exp = Index([x.ordinal for x in index])
tm.assert_index_equal(result, exp)

@pytest.mark.parametrize(
"freq,freq_depr",
[
("2M", "2ME"),
("2Q-MAR", "2QE-MAR"),
("2Y-FEB", "2YE-FEB"),
],
)
def test_period_index_frequency_ME_error_message(self, freq, freq_depr):
# GH#52064
msg = f"for Period, please use '{freq[1:]}' instead of '{freq_depr[1:]}'"

with pytest.raises(ValueError, match=msg):
PeriodIndex(["2020-01-01", "2020-01-02"], freq=freq_depr)

def test_H_deprecated_from_time_series(self):
# GH#52536
msg = "'H' is deprecated and will be removed in a future version."

with tm.assert_produces_warning(FutureWarning, match=msg):
index = period_range(freq="2H", start="1/1/2001", end="12/1/2009")
series = Series(1, index=index)
assert isinstance(series, Series)

@pytest.mark.parametrize("freq_depr", ["2A", "A-DEC", "200A-AUG"])
def test_a_deprecated_from_time_series(self, freq_depr):
# GH#52536
freq_msg = freq_depr[freq_depr.index("A") :]
msg = f"'{freq_msg}' is deprecated and will be removed in a future version, "
f"please use 'Y{freq_msg[1:]}' instead."

with tm.assert_produces_warning(FutureWarning, match=msg):
index = period_range(freq=freq_depr, start="1/1/2001", end="12/1/2009")
series = Series(1, index=index)
assert isinstance(series, Series)

@pytest.mark.parametrize("freq_depr", ["2SME", "2CBME", "2BYE"])
def test_period_index_frequency_invalid_freq(self, freq_depr):
# GH#9586
msg = f"Invalid frequency: {freq_depr[1:]}"

with pytest.raises(ValueError, match=msg):
period_range("2020-01", "2020-05", freq=freq_depr)


def test_maybe_convert_timedelta():
pi = PeriodIndex(["2000", "2001"], freq="D")
Expand Down
Loading