1import numpy as np
2import pytest
3
4import pandas as pd
5from pandas import Float64Index, Int64Index, RangeIndex, UInt64Index
6import pandas._testing as tm
7
8# ------------------------------------------------------------------
9# Helper Functions
10
11
12def id_func(x):
13    if isinstance(x, tuple):
14        assert len(x) == 2
15        return x[0].__name__ + "-" + str(x[1])
16    else:
17        return x.__name__
18
19
20# ------------------------------------------------------------------
21
22
23@pytest.fixture(params=[1, np.array(1, dtype=np.int64)])
24def one(request):
25    """
26    Several variants of integer value 1. The zero-dim integer array
27    behaves like an integer.
28
29    This fixture can be used to check that datetimelike indexes handle
30    addition and subtraction of integers and zero-dimensional arrays
31    of integers.
32
33    Examples
34    --------
35    >>> dti = pd.date_range('2016-01-01', periods=2, freq='H')
36    >>> dti
37    DatetimeIndex(['2016-01-01 00:00:00', '2016-01-01 01:00:00'],
38    dtype='datetime64[ns]', freq='H')
39    >>> dti + one
40    DatetimeIndex(['2016-01-01 01:00:00', '2016-01-01 02:00:00'],
41    dtype='datetime64[ns]', freq='H')
42    """
43    return request.param
44
45
46zeros = [
47    box_cls([0] * 5, dtype=dtype)
48    for box_cls in [pd.Index, np.array, pd.array]
49    for dtype in [np.int64, np.uint64, np.float64]
50]
51zeros.extend(
52    [box_cls([-0.0] * 5, dtype=np.float64) for box_cls in [pd.Index, np.array]]
53)
54zeros.extend([np.array(0, dtype=dtype) for dtype in [np.int64, np.uint64, np.float64]])
55zeros.extend([np.array(-0.0, dtype=np.float64)])
56zeros.extend([0, 0.0, -0.0])
57
58
59@pytest.fixture(params=zeros)
60def zero(request):
61    """
62    Several types of scalar zeros and length 5 vectors of zeros.
63
64    This fixture can be used to check that numeric-dtype indexes handle
65    division by any zero numeric-dtype.
66
67    Uses vector of length 5 for broadcasting with `numeric_idx` fixture,
68    which creates numeric-dtype vectors also of length 5.
69
70    Examples
71    --------
72    >>> arr = RangeIndex(5)
73    >>> arr / zeros
74    Float64Index([nan, inf, inf, inf, inf], dtype='float64')
75    """
76    return request.param
77
78
79# ------------------------------------------------------------------
80# Vector Fixtures
81
82
83@pytest.fixture(
84    params=[
85        Float64Index(np.arange(5, dtype="float64")),
86        Int64Index(np.arange(5, dtype="int64")),
87        UInt64Index(np.arange(5, dtype="uint64")),
88        RangeIndex(5),
89    ],
90    ids=lambda x: type(x).__name__,
91)
92def numeric_idx(request):
93    """
94    Several types of numeric-dtypes Index objects
95    """
96    return request.param
97
98
99# ------------------------------------------------------------------
100# Scalar Fixtures
101
102
103@pytest.fixture(
104    params=[
105        pd.Timedelta("5m4s").to_pytimedelta(),
106        pd.Timedelta("5m4s"),
107        pd.Timedelta("5m4s").to_timedelta64(),
108    ],
109    ids=lambda x: type(x).__name__,
110)
111def scalar_td(request):
112    """
113    Several variants of Timedelta scalars representing 5 minutes and 4 seconds
114    """
115    return request.param
116
117
118@pytest.fixture(
119    params=[
120        pd.offsets.Day(3),
121        pd.offsets.Hour(72),
122        pd.Timedelta(days=3).to_pytimedelta(),
123        pd.Timedelta("72:00:00"),
124        np.timedelta64(3, "D"),
125        np.timedelta64(72, "h"),
126    ],
127    ids=lambda x: type(x).__name__,
128)
129def three_days(request):
130    """
131    Several timedelta-like and DateOffset objects that each represent
132    a 3-day timedelta
133    """
134    return request.param
135
136
137@pytest.fixture(
138    params=[
139        pd.offsets.Hour(2),
140        pd.offsets.Minute(120),
141        pd.Timedelta(hours=2).to_pytimedelta(),
142        pd.Timedelta(seconds=2 * 3600),
143        np.timedelta64(2, "h"),
144        np.timedelta64(120, "m"),
145    ],
146    ids=lambda x: type(x).__name__,
147)
148def two_hours(request):
149    """
150    Several timedelta-like and DateOffset objects that each represent
151    a 2-hour timedelta
152    """
153    return request.param
154
155
156_common_mismatch = [
157    pd.offsets.YearBegin(2),
158    pd.offsets.MonthBegin(1),
159    pd.offsets.Minute(),
160]
161
162
163@pytest.fixture(
164    params=[
165        pd.Timedelta(minutes=30).to_pytimedelta(),
166        np.timedelta64(30, "s"),
167        pd.Timedelta(seconds=30),
168    ]
169    + _common_mismatch
170)
171def not_hourly(request):
172    """
173    Several timedelta-like and DateOffset instances that are _not_
174    compatible with Hourly frequencies.
175    """
176    return request.param
177
178
179@pytest.fixture(
180    params=[
181        np.timedelta64(4, "h"),
182        pd.Timedelta(hours=23).to_pytimedelta(),
183        pd.Timedelta("23:00:00"),
184    ]
185    + _common_mismatch
186)
187def not_daily(request):
188    """
189    Several timedelta-like and DateOffset instances that are _not_
190    compatible with Daily frequencies.
191    """
192    return request.param
193
194
195@pytest.fixture(
196    params=[
197        np.timedelta64(365, "D"),
198        pd.Timedelta(days=365).to_pytimedelta(),
199        pd.Timedelta(days=365),
200    ]
201    + _common_mismatch
202)
203def mismatched_freq(request):
204    """
205    Several timedelta-like and DateOffset instances that are _not_
206    compatible with Monthly or Annual frequencies.
207    """
208    return request.param
209
210
211# ------------------------------------------------------------------
212
213
214@pytest.fixture(params=[pd.Index, pd.Series, pd.DataFrame, pd.array], ids=id_func)
215def box_with_array(request):
216    """
217    Fixture to test behavior for Index, Series, DataFrame, and pandas Array
218    classes
219    """
220    return request.param
221
222
223@pytest.fixture(params=[pd.Index, pd.Series, tm.to_array, np.array, list], ids=id_func)
224def box_1d_array(request):
225    """
226    Fixture to test behavior for Index, Series, tm.to_array, numpy Array and list
227    classes
228    """
229    return request.param
230
231
232# alias so we can use the same fixture for multiple parameters in a test
233box_with_array2 = box_with_array
234