Skip to content

Commit 9db55a7

Browse files
authored
TST: Add test for where inplace (#44255)
1 parent 12afff1 commit 9db55a7

File tree

6 files changed

+123
-97
lines changed

6 files changed

+123
-97
lines changed

pandas/_testing/_hypothesis.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"""
2+
Hypothesis data generator helpers.
3+
"""
4+
from datetime import datetime
5+
6+
from hypothesis import strategies as st
7+
from hypothesis.extra.dateutil import timezones as dateutil_timezones
8+
from hypothesis.extra.pytz import timezones as pytz_timezones
9+
10+
from pandas.compat import is_platform_windows
11+
12+
import pandas as pd
13+
14+
from pandas.tseries.offsets import (
15+
BMonthBegin,
16+
BMonthEnd,
17+
BQuarterBegin,
18+
BQuarterEnd,
19+
BYearBegin,
20+
BYearEnd,
21+
MonthBegin,
22+
MonthEnd,
23+
QuarterBegin,
24+
QuarterEnd,
25+
YearBegin,
26+
YearEnd,
27+
)
28+
29+
OPTIONAL_INTS = st.lists(st.one_of(st.integers(), st.none()), max_size=10, min_size=3)
30+
31+
OPTIONAL_FLOATS = st.lists(st.one_of(st.floats(), st.none()), max_size=10, min_size=3)
32+
33+
OPTIONAL_TEXT = st.lists(st.one_of(st.none(), st.text()), max_size=10, min_size=3)
34+
35+
OPTIONAL_DICTS = st.lists(
36+
st.one_of(st.none(), st.dictionaries(st.text(), st.integers())),
37+
max_size=10,
38+
min_size=3,
39+
)
40+
41+
OPTIONAL_LISTS = st.lists(
42+
st.one_of(st.none(), st.lists(st.text(), max_size=10, min_size=3)),
43+
max_size=10,
44+
min_size=3,
45+
)
46+
47+
if is_platform_windows():
48+
DATETIME_NO_TZ = st.datetimes(min_value=datetime(1900, 1, 1))
49+
else:
50+
DATETIME_NO_TZ = st.datetimes()
51+
52+
DATETIME_JAN_1_1900_OPTIONAL_TZ = st.datetimes(
53+
min_value=pd.Timestamp(1900, 1, 1).to_pydatetime(),
54+
max_value=pd.Timestamp(1900, 1, 1).to_pydatetime(),
55+
timezones=st.one_of(st.none(), dateutil_timezones(), pytz_timezones()),
56+
)
57+
58+
DATETIME_IN_PD_TIMESTAMP_RANGE_NO_TZ = st.datetimes(
59+
min_value=pd.Timestamp.min.to_pydatetime(warn=False),
60+
max_value=pd.Timestamp.max.to_pydatetime(warn=False),
61+
)
62+
63+
INT_NEG_999_TO_POS_999 = st.integers(-999, 999)
64+
65+
# The strategy for each type is registered in conftest.py, as they don't carry
66+
# enough runtime information (e.g. type hints) to infer how to build them.
67+
YQM_OFFSET = st.one_of(
68+
*map(
69+
st.from_type,
70+
[
71+
MonthBegin,
72+
MonthEnd,
73+
BMonthBegin,
74+
BMonthEnd,
75+
QuarterBegin,
76+
QuarterEnd,
77+
BQuarterBegin,
78+
BQuarterEnd,
79+
YearBegin,
80+
YearEnd,
81+
BYearBegin,
82+
BYearEnd,
83+
],
84+
)
85+
)

pandas/tests/frame/indexing/test_where.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
from datetime import datetime
22

3+
from hypothesis import (
4+
given,
5+
strategies as st,
6+
)
37
import numpy as np
48
import pytest
59

@@ -16,6 +20,13 @@
1620
isna,
1721
)
1822
import pandas._testing as tm
23+
from pandas._testing._hypothesis import (
24+
OPTIONAL_DICTS,
25+
OPTIONAL_FLOATS,
26+
OPTIONAL_INTS,
27+
OPTIONAL_LISTS,
28+
OPTIONAL_TEXT,
29+
)
1930

2031

2132
@pytest.fixture(params=["default", "float_string", "mixed_float", "mixed_int"])
@@ -797,3 +808,16 @@ def test_where_columns_casting():
797808
result = df.where(pd.notnull(df), None)
798809
# make sure dtypes don't change
799810
tm.assert_frame_equal(expected, result)
811+
812+
813+
@given(
814+
data=st.one_of(
815+
OPTIONAL_DICTS, OPTIONAL_FLOATS, OPTIONAL_INTS, OPTIONAL_LISTS, OPTIONAL_TEXT
816+
)
817+
)
818+
def test_where_inplace_casting(data):
819+
# GH 22051
820+
df = DataFrame({"a": data})
821+
df_copy = df.where(pd.notnull(df), None).copy()
822+
df.where(pd.notnull(df), None, inplace=True)
823+
tm.assert_equal(df, df_copy)

pandas/tests/io/parser/test_parse_dates.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,14 @@
1414
from hypothesis import (
1515
given,
1616
settings,
17-
strategies as st,
1817
)
1918
import numpy as np
2019
import pytest
2120
import pytz
2221

2322
from pandas._libs.tslibs import parsing
2423
from pandas._libs.tslibs.parsing import parse_datetime_string
25-
from pandas.compat import (
26-
is_platform_windows,
27-
np_array_datetime64_compat,
28-
)
24+
from pandas.compat import np_array_datetime64_compat
2925
from pandas.compat.pyarrow import pa_version_under6p0
3026

3127
import pandas as pd
@@ -38,6 +34,7 @@
3834
Timestamp,
3935
)
4036
import pandas._testing as tm
37+
from pandas._testing._hypothesis import DATETIME_NO_TZ
4138
from pandas.core.indexes.datetimes import date_range
4239

4340
import pandas.io.date_converters as conv
@@ -52,12 +49,6 @@
5249
# constant
5350
_DEFAULT_DATETIME = datetime(1, 1, 1)
5451

55-
# Strategy for hypothesis
56-
if is_platform_windows():
57-
date_strategy = st.datetimes(min_value=datetime(1900, 1, 1))
58-
else:
59-
date_strategy = st.datetimes()
60-
6152

6253
@xfail_pyarrow
6354
def test_read_csv_with_custom_date_parser(all_parsers):
@@ -1683,7 +1674,7 @@ def _helper_hypothesis_delimited_date(call, date_string, **kwargs):
16831674

16841675

16851676
@skip_pyarrow
1686-
@given(date_strategy)
1677+
@given(DATETIME_NO_TZ)
16871678
@settings(deadline=None)
16881679
@pytest.mark.parametrize("delimiter", list(" -./"))
16891680
@pytest.mark.parametrize("dayfirst", [True, False])

pandas/tests/tseries/offsets/test_offsets_properties.py

Lines changed: 5 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -7,92 +7,26 @@
77
You may wish to consult the previous version for inspiration on further
88
tests, or when trying to pin down the bugs exposed by the tests below.
99
"""
10-
import warnings
11-
1210
from hypothesis import (
1311
assume,
1412
given,
15-
strategies as st,
1613
)
1714
from hypothesis.errors import Flaky
18-
from hypothesis.extra.dateutil import timezones as dateutil_timezones
19-
from hypothesis.extra.pytz import timezones as pytz_timezones
2015
import pytest
2116
import pytz
2217

2318
import pandas as pd
24-
from pandas import Timestamp
25-
26-
from pandas.tseries.offsets import (
27-
BMonthBegin,
28-
BMonthEnd,
29-
BQuarterBegin,
30-
BQuarterEnd,
31-
BYearBegin,
32-
BYearEnd,
33-
MonthBegin,
34-
MonthEnd,
35-
QuarterBegin,
36-
QuarterEnd,
37-
YearBegin,
38-
YearEnd,
39-
)
40-
41-
# ----------------------------------------------------------------
42-
# Helpers for generating random data
43-
44-
with warnings.catch_warnings():
45-
warnings.simplefilter("ignore")
46-
min_dt = Timestamp(1900, 1, 1).to_pydatetime()
47-
max_dt = Timestamp(1900, 1, 1).to_pydatetime()
48-
49-
gen_date_range = st.builds(
50-
pd.date_range,
51-
start=st.datetimes(
52-
# TODO: Choose the min/max values more systematically
53-
min_value=Timestamp(1900, 1, 1).to_pydatetime(),
54-
max_value=Timestamp(2100, 1, 1).to_pydatetime(),
55-
),
56-
periods=st.integers(min_value=2, max_value=100),
57-
freq=st.sampled_from("Y Q M D H T s ms us ns".split()),
58-
tz=st.one_of(st.none(), dateutil_timezones(), pytz_timezones()),
19+
from pandas._testing._hypothesis import (
20+
DATETIME_JAN_1_1900_OPTIONAL_TZ,
21+
YQM_OFFSET,
5922
)
6023

61-
gen_random_datetime = st.datetimes(
62-
min_value=min_dt,
63-
max_value=max_dt,
64-
timezones=st.one_of(st.none(), dateutil_timezones(), pytz_timezones()),
65-
)
66-
67-
# The strategy for each type is registered in conftest.py, as they don't carry
68-
# enough runtime information (e.g. type hints) to infer how to build them.
69-
gen_yqm_offset = st.one_of(
70-
*map(
71-
st.from_type,
72-
[
73-
MonthBegin,
74-
MonthEnd,
75-
BMonthBegin,
76-
BMonthEnd,
77-
QuarterBegin,
78-
QuarterEnd,
79-
BQuarterBegin,
80-
BQuarterEnd,
81-
YearBegin,
82-
YearEnd,
83-
BYearBegin,
84-
BYearEnd,
85-
],
86-
)
87-
)
88-
89-
9024
# ----------------------------------------------------------------
9125
# Offset-specific behaviour tests
9226

9327

9428
@pytest.mark.arm_slow
95-
@given(gen_random_datetime, gen_yqm_offset)
29+
@given(DATETIME_JAN_1_1900_OPTIONAL_TZ, YQM_OFFSET)
9630
def test_on_offset_implementations(dt, offset):
9731
assume(not offset.normalize)
9832
# check that the class-specific implementations of is_on_offset match
@@ -112,7 +46,7 @@ def test_on_offset_implementations(dt, offset):
11246

11347

11448
@pytest.mark.xfail(strict=False, raises=Flaky, reason="unreliable test timings")
115-
@given(gen_yqm_offset)
49+
@given(YQM_OFFSET)
11650
def test_shift_across_dst(offset):
11751
# GH#18319 check that 1) timezone is correctly normalized and
11852
# 2) that hour is not incorrectly changed by this normalization

pandas/tests/tseries/offsets/test_ticks.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
example,
1212
given,
1313
settings,
14-
strategies as st,
1514
)
1615
import numpy as np
1716
import pytest
@@ -23,6 +22,7 @@
2322
Timestamp,
2423
)
2524
import pandas._testing as tm
25+
from pandas._testing._hypothesis import INT_NEG_999_TO_POS_999
2626
from pandas.tests.tseries.offsets.common import assert_offset_equal
2727

2828
from pandas.tseries import offsets
@@ -66,7 +66,7 @@ def test_delta_to_tick():
6666
@example(n=2, m=3)
6767
@example(n=800, m=300)
6868
@example(n=1000, m=5)
69-
@given(n=st.integers(-999, 999), m=st.integers(-999, 999))
69+
@given(n=INT_NEG_999_TO_POS_999, m=INT_NEG_999_TO_POS_999)
7070
def test_tick_add_sub(cls, n, m):
7171
# For all Tick subclasses and all integers n, m, we should have
7272
# tick(n) + tick(m) == tick(n+m)
@@ -86,7 +86,7 @@ def test_tick_add_sub(cls, n, m):
8686
@pytest.mark.parametrize("cls", tick_classes)
8787
@settings(deadline=None)
8888
@example(n=2, m=3)
89-
@given(n=st.integers(-999, 999), m=st.integers(-999, 999))
89+
@given(n=INT_NEG_999_TO_POS_999, m=INT_NEG_999_TO_POS_999)
9090
def test_tick_equality(cls, n, m):
9191
assume(m != n)
9292
# tick == tock iff tick.n == tock.n

pandas/tests/tslibs/test_ccalendar.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,13 @@
33
datetime,
44
)
55

6-
from hypothesis import (
7-
given,
8-
strategies as st,
9-
)
6+
from hypothesis import given
107
import numpy as np
118
import pytest
129

1310
from pandas._libs.tslibs import ccalendar
1411

15-
import pandas as pd
12+
from pandas._testing._hypothesis import DATETIME_IN_PD_TIMESTAMP_RANGE_NO_TZ
1613

1714

1815
@pytest.mark.parametrize(
@@ -59,12 +56,7 @@ def test_dt_correct_iso_8601_year_week_and_day(input_date_tuple, expected_iso_tu
5956
assert result == expected_iso_tuple
6057

6158

62-
@given(
63-
st.datetimes(
64-
min_value=pd.Timestamp.min.to_pydatetime(warn=False),
65-
max_value=pd.Timestamp.max.to_pydatetime(warn=False),
66-
)
67-
)
59+
@given(DATETIME_IN_PD_TIMESTAMP_RANGE_NO_TZ)
6860
def test_isocalendar(dt):
6961
expected = dt.isocalendar()
7062
result = ccalendar.get_iso_calendar(dt.year, dt.month, dt.day)

0 commit comments

Comments
 (0)