venv
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,26 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(params=[True, False])
|
||||
def check_dtype(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(params=[True, False])
|
||||
def check_exact(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(params=[True, False])
|
||||
def check_index_type(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(params=[0.5e-3, 0.5e-5])
|
||||
def rtol(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(params=[True, False])
|
||||
def check_categorical(request):
|
||||
return request.param
|
@ -0,0 +1,586 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
NA,
|
||||
DataFrame,
|
||||
Index,
|
||||
NaT,
|
||||
Series,
|
||||
Timestamp,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def _assert_almost_equal_both(a, b, **kwargs):
|
||||
"""
|
||||
Check that two objects are approximately equal.
|
||||
|
||||
This check is performed commutatively.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a : object
|
||||
The first object to compare.
|
||||
b : object
|
||||
The second object to compare.
|
||||
**kwargs
|
||||
The arguments passed to `tm.assert_almost_equal`.
|
||||
"""
|
||||
tm.assert_almost_equal(a, b, **kwargs)
|
||||
tm.assert_almost_equal(b, a, **kwargs)
|
||||
|
||||
|
||||
def _assert_not_almost_equal(a, b, **kwargs):
|
||||
"""
|
||||
Check that two objects are not approximately equal.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a : object
|
||||
The first object to compare.
|
||||
b : object
|
||||
The second object to compare.
|
||||
**kwargs
|
||||
The arguments passed to `tm.assert_almost_equal`.
|
||||
"""
|
||||
try:
|
||||
tm.assert_almost_equal(a, b, **kwargs)
|
||||
msg = f"{a} and {b} were approximately equal when they shouldn't have been"
|
||||
pytest.fail(reason=msg)
|
||||
except AssertionError:
|
||||
pass
|
||||
|
||||
|
||||
def _assert_not_almost_equal_both(a, b, **kwargs):
|
||||
"""
|
||||
Check that two objects are not approximately equal.
|
||||
|
||||
This check is performed commutatively.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a : object
|
||||
The first object to compare.
|
||||
b : object
|
||||
The second object to compare.
|
||||
**kwargs
|
||||
The arguments passed to `tm.assert_almost_equal`.
|
||||
"""
|
||||
_assert_not_almost_equal(a, b, **kwargs)
|
||||
_assert_not_almost_equal(b, a, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b",
|
||||
[
|
||||
(1.1, 1.1),
|
||||
(1.1, 1.100001),
|
||||
(np.int16(1), 1.000001),
|
||||
(np.float64(1.1), 1.1),
|
||||
(np.uint32(5), 5),
|
||||
],
|
||||
)
|
||||
def test_assert_almost_equal_numbers(a, b):
|
||||
_assert_almost_equal_both(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b",
|
||||
[
|
||||
(1.1, 1),
|
||||
(1.1, True),
|
||||
(1, 2),
|
||||
(1.0001, np.int16(1)),
|
||||
# The following two examples are not "almost equal" due to tol.
|
||||
(0.1, 0.1001),
|
||||
(0.0011, 0.0012),
|
||||
],
|
||||
)
|
||||
def test_assert_not_almost_equal_numbers(a, b):
|
||||
_assert_not_almost_equal_both(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b",
|
||||
[
|
||||
(1.1, 1.1),
|
||||
(1.1, 1.100001),
|
||||
(1.1, 1.1001),
|
||||
(0.000001, 0.000005),
|
||||
(1000.0, 1000.0005),
|
||||
# Testing this example, as per #13357
|
||||
(0.000011, 0.000012),
|
||||
],
|
||||
)
|
||||
def test_assert_almost_equal_numbers_atol(a, b):
|
||||
# Equivalent to the deprecated check_less_precise=True, enforced in 2.0
|
||||
_assert_almost_equal_both(a, b, rtol=0.5e-3, atol=0.5e-3)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a,b", [(1.1, 1.11), (0.1, 0.101), (0.000011, 0.001012)])
|
||||
def test_assert_not_almost_equal_numbers_atol(a, b):
|
||||
_assert_not_almost_equal_both(a, b, atol=1e-3)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b",
|
||||
[
|
||||
(1.1, 1.1),
|
||||
(1.1, 1.100001),
|
||||
(1.1, 1.1001),
|
||||
(1000.0, 1000.0005),
|
||||
(1.1, 1.11),
|
||||
(0.1, 0.101),
|
||||
],
|
||||
)
|
||||
def test_assert_almost_equal_numbers_rtol(a, b):
|
||||
_assert_almost_equal_both(a, b, rtol=0.05)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a,b", [(0.000011, 0.000012), (0.000001, 0.000005)])
|
||||
def test_assert_not_almost_equal_numbers_rtol(a, b):
|
||||
_assert_not_almost_equal_both(a, b, rtol=0.05)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b,rtol",
|
||||
[
|
||||
(1.00001, 1.00005, 0.001),
|
||||
(-0.908356 + 0.2j, -0.908358 + 0.2j, 1e-3),
|
||||
(0.1 + 1.009j, 0.1 + 1.006j, 0.1),
|
||||
(0.1001 + 2.0j, 0.1 + 2.001j, 0.01),
|
||||
],
|
||||
)
|
||||
def test_assert_almost_equal_complex_numbers(a, b, rtol):
|
||||
_assert_almost_equal_both(a, b, rtol=rtol)
|
||||
_assert_almost_equal_both(np.complex64(a), np.complex64(b), rtol=rtol)
|
||||
_assert_almost_equal_both(np.complex128(a), np.complex128(b), rtol=rtol)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b,rtol",
|
||||
[
|
||||
(0.58310768, 0.58330768, 1e-7),
|
||||
(-0.908 + 0.2j, -0.978 + 0.2j, 0.001),
|
||||
(0.1 + 1j, 0.1 + 2j, 0.01),
|
||||
(-0.132 + 1.001j, -0.132 + 1.005j, 1e-5),
|
||||
(0.58310768j, 0.58330768j, 1e-9),
|
||||
],
|
||||
)
|
||||
def test_assert_not_almost_equal_complex_numbers(a, b, rtol):
|
||||
_assert_not_almost_equal_both(a, b, rtol=rtol)
|
||||
_assert_not_almost_equal_both(np.complex64(a), np.complex64(b), rtol=rtol)
|
||||
_assert_not_almost_equal_both(np.complex128(a), np.complex128(b), rtol=rtol)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a,b", [(0, 0), (0, 0.0), (0, np.float64(0)), (0.00000001, 0)])
|
||||
def test_assert_almost_equal_numbers_with_zeros(a, b):
|
||||
_assert_almost_equal_both(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a,b", [(0.001, 0), (1, 0)])
|
||||
def test_assert_not_almost_equal_numbers_with_zeros(a, b):
|
||||
_assert_not_almost_equal_both(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a,b", [(1, "abc"), (1, [1]), (1, object())])
|
||||
def test_assert_not_almost_equal_numbers_with_mixed(a, b):
|
||||
_assert_not_almost_equal_both(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"left_dtype", ["M8[ns]", "m8[ns]", "float64", "int64", "object"]
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"right_dtype", ["M8[ns]", "m8[ns]", "float64", "int64", "object"]
|
||||
)
|
||||
def test_assert_almost_equal_edge_case_ndarrays(left_dtype, right_dtype):
|
||||
# Empty compare.
|
||||
_assert_almost_equal_both(
|
||||
np.array([], dtype=left_dtype),
|
||||
np.array([], dtype=right_dtype),
|
||||
check_dtype=False,
|
||||
)
|
||||
|
||||
|
||||
def test_assert_almost_equal_sets():
|
||||
# GH#51727
|
||||
_assert_almost_equal_both({1, 2, 3}, {1, 2, 3})
|
||||
|
||||
|
||||
def test_assert_almost_not_equal_sets():
|
||||
# GH#51727
|
||||
msg = r"{1, 2, 3} != {1, 2, 4}"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
_assert_almost_equal_both({1, 2, 3}, {1, 2, 4})
|
||||
|
||||
|
||||
def test_assert_almost_equal_dicts():
|
||||
_assert_almost_equal_both({"a": 1, "b": 2}, {"a": 1, "b": 2})
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b",
|
||||
[
|
||||
({"a": 1, "b": 2}, {"a": 1, "b": 3}),
|
||||
({"a": 1, "b": 2}, {"a": 1, "b": 2, "c": 3}),
|
||||
({"a": 1}, 1),
|
||||
({"a": 1}, "abc"),
|
||||
({"a": 1}, [1]),
|
||||
],
|
||||
)
|
||||
def test_assert_not_almost_equal_dicts(a, b):
|
||||
_assert_not_almost_equal_both(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("val", [1, 2])
|
||||
def test_assert_almost_equal_dict_like_object(val):
|
||||
dict_val = 1
|
||||
real_dict = {"a": val}
|
||||
|
||||
class DictLikeObj:
|
||||
def keys(self):
|
||||
return ("a",)
|
||||
|
||||
def __getitem__(self, item):
|
||||
if item == "a":
|
||||
return dict_val
|
||||
|
||||
func = (
|
||||
_assert_almost_equal_both if val == dict_val else _assert_not_almost_equal_both
|
||||
)
|
||||
func(real_dict, DictLikeObj(), check_dtype=False)
|
||||
|
||||
|
||||
def test_assert_almost_equal_strings():
|
||||
_assert_almost_equal_both("abc", "abc")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b", [("abc", "abcd"), ("abc", "abd"), ("abc", 1), ("abc", [1])]
|
||||
)
|
||||
def test_assert_not_almost_equal_strings(a, b):
|
||||
_assert_not_almost_equal_both(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b", [([1, 2, 3], [1, 2, 3]), (np.array([1, 2, 3]), np.array([1, 2, 3]))]
|
||||
)
|
||||
def test_assert_almost_equal_iterables(a, b):
|
||||
_assert_almost_equal_both(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b",
|
||||
[
|
||||
# Class is different.
|
||||
(np.array([1, 2, 3]), [1, 2, 3]),
|
||||
# Dtype is different.
|
||||
(np.array([1, 2, 3]), np.array([1.0, 2.0, 3.0])),
|
||||
# Can't compare generators.
|
||||
(iter([1, 2, 3]), [1, 2, 3]),
|
||||
([1, 2, 3], [1, 2, 4]),
|
||||
([1, 2, 3], [1, 2, 3, 4]),
|
||||
([1, 2, 3], 1),
|
||||
],
|
||||
)
|
||||
def test_assert_not_almost_equal_iterables(a, b):
|
||||
_assert_not_almost_equal(a, b)
|
||||
|
||||
|
||||
def test_assert_almost_equal_null():
|
||||
_assert_almost_equal_both(None, None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a,b", [(None, np.nan), (None, 0), (np.nan, 0)])
|
||||
def test_assert_not_almost_equal_null(a, b):
|
||||
_assert_not_almost_equal(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b",
|
||||
[
|
||||
(np.inf, np.inf),
|
||||
(np.inf, float("inf")),
|
||||
(np.array([np.inf, np.nan, -np.inf]), np.array([np.inf, np.nan, -np.inf])),
|
||||
],
|
||||
)
|
||||
def test_assert_almost_equal_inf(a, b):
|
||||
_assert_almost_equal_both(a, b)
|
||||
|
||||
|
||||
objs = [NA, np.nan, NaT, None, np.datetime64("NaT"), np.timedelta64("NaT")]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("left", objs)
|
||||
@pytest.mark.parametrize("right", objs)
|
||||
def test_mismatched_na_assert_almost_equal_deprecation(left, right):
|
||||
left_arr = np.array([left], dtype=object)
|
||||
right_arr = np.array([right], dtype=object)
|
||||
|
||||
msg = "Mismatched null-like values"
|
||||
|
||||
if left is right:
|
||||
_assert_almost_equal_both(left, right, check_dtype=False)
|
||||
tm.assert_numpy_array_equal(left_arr, right_arr)
|
||||
tm.assert_index_equal(
|
||||
Index(left_arr, dtype=object), Index(right_arr, dtype=object)
|
||||
)
|
||||
tm.assert_series_equal(
|
||||
Series(left_arr, dtype=object), Series(right_arr, dtype=object)
|
||||
)
|
||||
tm.assert_frame_equal(
|
||||
DataFrame(left_arr, dtype=object), DataFrame(right_arr, dtype=object)
|
||||
)
|
||||
|
||||
else:
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
_assert_almost_equal_both(left, right, check_dtype=False)
|
||||
|
||||
# TODO: to get the same deprecation in assert_numpy_array_equal we need
|
||||
# to change/deprecate the default for strict_nan to become True
|
||||
# TODO: to get the same deprecation in assert_index_equal we need to
|
||||
# change/deprecate array_equivalent_object to be stricter, as
|
||||
# assert_index_equal uses Index.equal which uses array_equivalent.
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
tm.assert_series_equal(
|
||||
Series(left_arr, dtype=object), Series(right_arr, dtype=object)
|
||||
)
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
tm.assert_frame_equal(
|
||||
DataFrame(left_arr, dtype=object), DataFrame(right_arr, dtype=object)
|
||||
)
|
||||
|
||||
|
||||
def test_assert_not_almost_equal_inf():
|
||||
_assert_not_almost_equal_both(np.inf, 0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b",
|
||||
[
|
||||
(Index([1.0, 1.1]), Index([1.0, 1.100001])),
|
||||
(Series([1.0, 1.1]), Series([1.0, 1.100001])),
|
||||
(np.array([1.1, 2.000001]), np.array([1.1, 2.0])),
|
||||
(DataFrame({"a": [1.0, 1.1]}), DataFrame({"a": [1.0, 1.100001]})),
|
||||
],
|
||||
)
|
||||
def test_assert_almost_equal_pandas(a, b):
|
||||
_assert_almost_equal_both(a, b)
|
||||
|
||||
|
||||
def test_assert_almost_equal_object():
|
||||
a = [Timestamp("2011-01-01"), Timestamp("2011-01-01")]
|
||||
b = [Timestamp("2011-01-01"), Timestamp("2011-01-01")]
|
||||
_assert_almost_equal_both(a, b)
|
||||
|
||||
|
||||
def test_assert_almost_equal_value_mismatch():
|
||||
msg = "expected 2\\.00000 but got 1\\.00000, with rtol=1e-05, atol=1e-08"
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal(1, 2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b,klass1,klass2",
|
||||
[(np.array([1]), 1, "ndarray", "int"), (1, np.array([1]), "int", "ndarray")],
|
||||
)
|
||||
def test_assert_almost_equal_class_mismatch(a, b, klass1, klass2):
|
||||
msg = f"""numpy array are different
|
||||
|
||||
numpy array classes are different
|
||||
\\[left\\]: {klass1}
|
||||
\\[right\\]: {klass2}"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal(a, b)
|
||||
|
||||
|
||||
def test_assert_almost_equal_value_mismatch1():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(66\\.66667 %\\)
|
||||
\\[left\\]: \\[nan, 2\\.0, 3\\.0\\]
|
||||
\\[right\\]: \\[1\\.0, nan, 3\\.0\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal(np.array([np.nan, 2, 3]), np.array([1, np.nan, 3]))
|
||||
|
||||
|
||||
def test_assert_almost_equal_value_mismatch2():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(50\\.0 %\\)
|
||||
\\[left\\]: \\[1, 2\\]
|
||||
\\[right\\]: \\[1, 3\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal(np.array([1, 2]), np.array([1, 3]))
|
||||
|
||||
|
||||
def test_assert_almost_equal_value_mismatch3():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(16\\.66667 %\\)
|
||||
\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\], \\[5, 6\\]\\]
|
||||
\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\], \\[5, 6\\]\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal(
|
||||
np.array([[1, 2], [3, 4], [5, 6]]), np.array([[1, 3], [3, 4], [5, 6]])
|
||||
)
|
||||
|
||||
|
||||
def test_assert_almost_equal_value_mismatch4():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(25\\.0 %\\)
|
||||
\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\]\\]
|
||||
\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\]\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal(np.array([[1, 2], [3, 4]]), np.array([[1, 3], [3, 4]]))
|
||||
|
||||
|
||||
def test_assert_almost_equal_shape_mismatch_override():
|
||||
msg = """Index are different
|
||||
|
||||
Index shapes are different
|
||||
\\[left\\]: \\(2L*,\\)
|
||||
\\[right\\]: \\(3L*,\\)"""
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal(np.array([1, 2]), np.array([3, 4, 5]), obj="Index")
|
||||
|
||||
|
||||
def test_assert_almost_equal_unicode():
|
||||
# see gh-20503
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(33\\.33333 %\\)
|
||||
\\[left\\]: \\[á, à, ä\\]
|
||||
\\[right\\]: \\[á, à, å\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal(np.array(["á", "à", "ä"]), np.array(["á", "à", "å"]))
|
||||
|
||||
|
||||
def test_assert_almost_equal_timestamp():
|
||||
a = np.array([Timestamp("2011-01-01"), Timestamp("2011-01-01")])
|
||||
b = np.array([Timestamp("2011-01-01"), Timestamp("2011-01-02")])
|
||||
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(50\\.0 %\\)
|
||||
\\[left\\]: \\[2011-01-01 00:00:00, 2011-01-01 00:00:00\\]
|
||||
\\[right\\]: \\[2011-01-01 00:00:00, 2011-01-02 00:00:00\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal(a, b)
|
||||
|
||||
|
||||
def test_assert_almost_equal_iterable_length_mismatch():
|
||||
msg = """Iterable are different
|
||||
|
||||
Iterable length are different
|
||||
\\[left\\]: 2
|
||||
\\[right\\]: 3"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal([1, 2], [3, 4, 5])
|
||||
|
||||
|
||||
def test_assert_almost_equal_iterable_values_mismatch():
|
||||
msg = """Iterable are different
|
||||
|
||||
Iterable values are different \\(50\\.0 %\\)
|
||||
\\[left\\]: \\[1, 2\\]
|
||||
\\[right\\]: \\[1, 3\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_almost_equal([1, 2], [1, 3])
|
||||
|
||||
|
||||
subarr = np.empty(2, dtype=object)
|
||||
subarr[:] = [np.array([None, "b"], dtype=object), np.array(["c", "d"], dtype=object)]
|
||||
|
||||
NESTED_CASES = [
|
||||
# nested array
|
||||
(
|
||||
np.array([np.array([50, 70, 90]), np.array([20, 30])], dtype=object),
|
||||
np.array([np.array([50, 70, 90]), np.array([20, 30])], dtype=object),
|
||||
),
|
||||
# >1 level of nesting
|
||||
(
|
||||
np.array(
|
||||
[
|
||||
np.array([np.array([50, 70]), np.array([90])], dtype=object),
|
||||
np.array([np.array([20, 30])], dtype=object),
|
||||
],
|
||||
dtype=object,
|
||||
),
|
||||
np.array(
|
||||
[
|
||||
np.array([np.array([50, 70]), np.array([90])], dtype=object),
|
||||
np.array([np.array([20, 30])], dtype=object),
|
||||
],
|
||||
dtype=object,
|
||||
),
|
||||
),
|
||||
# lists
|
||||
(
|
||||
np.array([[50, 70, 90], [20, 30]], dtype=object),
|
||||
np.array([[50, 70, 90], [20, 30]], dtype=object),
|
||||
),
|
||||
# mixed array/list
|
||||
(
|
||||
np.array([np.array([1, 2, 3]), np.array([4, 5])], dtype=object),
|
||||
np.array([[1, 2, 3], [4, 5]], dtype=object),
|
||||
),
|
||||
(
|
||||
np.array(
|
||||
[
|
||||
np.array([np.array([1, 2, 3]), np.array([4, 5])], dtype=object),
|
||||
np.array(
|
||||
[np.array([6]), np.array([7, 8]), np.array([9])], dtype=object
|
||||
),
|
||||
],
|
||||
dtype=object,
|
||||
),
|
||||
np.array([[[1, 2, 3], [4, 5]], [[6], [7, 8], [9]]], dtype=object),
|
||||
),
|
||||
# same-length lists
|
||||
(
|
||||
np.array([subarr, None], dtype=object),
|
||||
np.array([[[None, "b"], ["c", "d"]], None], dtype=object),
|
||||
),
|
||||
# dicts
|
||||
(
|
||||
np.array([{"f1": 1, "f2": np.array(["a", "b"], dtype=object)}], dtype=object),
|
||||
np.array([{"f1": 1, "f2": np.array(["a", "b"], dtype=object)}], dtype=object),
|
||||
),
|
||||
(
|
||||
np.array([{"f1": 1, "f2": np.array(["a", "b"], dtype=object)}], dtype=object),
|
||||
np.array([{"f1": 1, "f2": ["a", "b"]}], dtype=object),
|
||||
),
|
||||
# array/list of dicts
|
||||
(
|
||||
np.array(
|
||||
[
|
||||
np.array(
|
||||
[{"f1": 1, "f2": np.array(["a", "b"], dtype=object)}], dtype=object
|
||||
),
|
||||
np.array([], dtype=object),
|
||||
],
|
||||
dtype=object,
|
||||
),
|
||||
np.array([[{"f1": 1, "f2": ["a", "b"]}], []], dtype=object),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:elementwise comparison failed:DeprecationWarning")
|
||||
@pytest.mark.parametrize("a,b", NESTED_CASES)
|
||||
def test_assert_almost_equal_array_nested(a, b):
|
||||
_assert_almost_equal_both(a, b)
|
@ -0,0 +1,33 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from pandas.core.dtypes.common import is_float
|
||||
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def test_assert_attr_equal(nulls_fixture):
|
||||
obj = SimpleNamespace()
|
||||
obj.na_value = nulls_fixture
|
||||
tm.assert_attr_equal("na_value", obj, obj)
|
||||
|
||||
|
||||
def test_assert_attr_equal_different_nulls(nulls_fixture, nulls_fixture2):
|
||||
obj = SimpleNamespace()
|
||||
obj.na_value = nulls_fixture
|
||||
|
||||
obj2 = SimpleNamespace()
|
||||
obj2.na_value = nulls_fixture2
|
||||
|
||||
if nulls_fixture is nulls_fixture2:
|
||||
tm.assert_attr_equal("na_value", obj, obj2)
|
||||
elif is_float(nulls_fixture) and is_float(nulls_fixture2):
|
||||
# we consider float("nan") and np.float64("nan") to be equivalent
|
||||
tm.assert_attr_equal("na_value", obj, obj2)
|
||||
elif type(nulls_fixture) is type(nulls_fixture2):
|
||||
# e.g. Decimal("NaN")
|
||||
tm.assert_attr_equal("na_value", obj, obj2)
|
||||
else:
|
||||
with pytest.raises(AssertionError, match='"na_value" are different'):
|
||||
tm.assert_attr_equal("na_value", obj, obj2)
|
@ -0,0 +1,90 @@
|
||||
import pytest
|
||||
|
||||
from pandas import Categorical
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"c",
|
||||
[Categorical([1, 2, 3, 4]), Categorical([1, 2, 3, 4], categories=[1, 2, 3, 4, 5])],
|
||||
)
|
||||
def test_categorical_equal(c):
|
||||
tm.assert_categorical_equal(c, c)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("check_category_order", [True, False])
|
||||
def test_categorical_equal_order_mismatch(check_category_order):
|
||||
c1 = Categorical([1, 2, 3, 4], categories=[1, 2, 3, 4])
|
||||
c2 = Categorical([1, 2, 3, 4], categories=[4, 3, 2, 1])
|
||||
kwargs = {"check_category_order": check_category_order}
|
||||
|
||||
if check_category_order:
|
||||
msg = """Categorical\\.categories are different
|
||||
|
||||
Categorical\\.categories values are different \\(100\\.0 %\\)
|
||||
\\[left\\]: Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)
|
||||
\\[right\\]: Index\\(\\[4, 3, 2, 1\\], dtype='int64'\\)"""
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_categorical_equal(c1, c2, **kwargs)
|
||||
else:
|
||||
tm.assert_categorical_equal(c1, c2, **kwargs)
|
||||
|
||||
|
||||
def test_categorical_equal_categories_mismatch():
|
||||
msg = """Categorical\\.categories are different
|
||||
|
||||
Categorical\\.categories values are different \\(25\\.0 %\\)
|
||||
\\[left\\]: Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)
|
||||
\\[right\\]: Index\\(\\[1, 2, 3, 5\\], dtype='int64'\\)"""
|
||||
|
||||
c1 = Categorical([1, 2, 3, 4])
|
||||
c2 = Categorical([1, 2, 3, 5])
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_categorical_equal(c1, c2)
|
||||
|
||||
|
||||
def test_categorical_equal_codes_mismatch():
|
||||
categories = [1, 2, 3, 4]
|
||||
msg = """Categorical\\.codes are different
|
||||
|
||||
Categorical\\.codes values are different \\(50\\.0 %\\)
|
||||
\\[left\\]: \\[0, 1, 3, 2\\]
|
||||
\\[right\\]: \\[0, 1, 2, 3\\]"""
|
||||
|
||||
c1 = Categorical([1, 2, 4, 3], categories=categories)
|
||||
c2 = Categorical([1, 2, 3, 4], categories=categories)
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_categorical_equal(c1, c2)
|
||||
|
||||
|
||||
def test_categorical_equal_ordered_mismatch():
|
||||
data = [1, 2, 3, 4]
|
||||
msg = """Categorical are different
|
||||
|
||||
Attribute "ordered" are different
|
||||
\\[left\\]: False
|
||||
\\[right\\]: True"""
|
||||
|
||||
c1 = Categorical(data, ordered=False)
|
||||
c2 = Categorical(data, ordered=True)
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_categorical_equal(c1, c2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("obj", ["index", "foo", "pandas"])
|
||||
def test_categorical_equal_object_override(obj):
|
||||
data = [1, 2, 3, 4]
|
||||
msg = f"""{obj} are different
|
||||
|
||||
Attribute "ordered" are different
|
||||
\\[left\\]: False
|
||||
\\[right\\]: True"""
|
||||
|
||||
c1 = Categorical(data, ordered=False)
|
||||
c2 = Categorical(data, ordered=True)
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_categorical_equal(c1, c2, obj=obj)
|
@ -0,0 +1,126 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
Timestamp,
|
||||
array,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
from pandas.core.arrays.sparse import SparseArray
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"kwargs",
|
||||
[
|
||||
{}, # Default is check_exact=False
|
||||
{"check_exact": False},
|
||||
{"check_exact": True},
|
||||
],
|
||||
)
|
||||
def test_assert_extension_array_equal_not_exact(kwargs):
|
||||
# see gh-23709
|
||||
arr1 = SparseArray([-0.17387645482451206, 0.3414148016424936])
|
||||
arr2 = SparseArray([-0.17387645482451206, 0.3414148016424937])
|
||||
|
||||
if kwargs.get("check_exact", False):
|
||||
msg = """\
|
||||
ExtensionArray are different
|
||||
|
||||
ExtensionArray values are different \\(50\\.0 %\\)
|
||||
\\[left\\]: \\[-0\\.17387645482.*, 0\\.341414801642.*\\]
|
||||
\\[right\\]: \\[-0\\.17387645482.*, 0\\.341414801642.*\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_extension_array_equal(arr1, arr2, **kwargs)
|
||||
else:
|
||||
tm.assert_extension_array_equal(arr1, arr2, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("decimals", range(10))
|
||||
def test_assert_extension_array_equal_less_precise(decimals):
|
||||
rtol = 0.5 * 10**-decimals
|
||||
arr1 = SparseArray([0.5, 0.123456])
|
||||
arr2 = SparseArray([0.5, 0.123457])
|
||||
|
||||
if decimals >= 5:
|
||||
msg = """\
|
||||
ExtensionArray are different
|
||||
|
||||
ExtensionArray values are different \\(50\\.0 %\\)
|
||||
\\[left\\]: \\[0\\.5, 0\\.123456\\]
|
||||
\\[right\\]: \\[0\\.5, 0\\.123457\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_extension_array_equal(arr1, arr2, rtol=rtol)
|
||||
else:
|
||||
tm.assert_extension_array_equal(arr1, arr2, rtol=rtol)
|
||||
|
||||
|
||||
def test_assert_extension_array_equal_dtype_mismatch(check_dtype):
|
||||
end = 5
|
||||
kwargs = {"check_dtype": check_dtype}
|
||||
|
||||
arr1 = SparseArray(np.arange(end, dtype="int64"))
|
||||
arr2 = SparseArray(np.arange(end, dtype="int32"))
|
||||
|
||||
if check_dtype:
|
||||
msg = """\
|
||||
ExtensionArray are different
|
||||
|
||||
Attribute "dtype" are different
|
||||
\\[left\\]: Sparse\\[int64, 0\\]
|
||||
\\[right\\]: Sparse\\[int32, 0\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_extension_array_equal(arr1, arr2, **kwargs)
|
||||
else:
|
||||
tm.assert_extension_array_equal(arr1, arr2, **kwargs)
|
||||
|
||||
|
||||
def test_assert_extension_array_equal_missing_values():
|
||||
arr1 = SparseArray([np.nan, 1, 2, np.nan])
|
||||
arr2 = SparseArray([np.nan, 1, 2, 3])
|
||||
|
||||
msg = """\
|
||||
ExtensionArray NA mask are different
|
||||
|
||||
ExtensionArray NA mask values are different \\(25\\.0 %\\)
|
||||
\\[left\\]: \\[True, False, False, True\\]
|
||||
\\[right\\]: \\[True, False, False, False\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_extension_array_equal(arr1, arr2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("side", ["left", "right"])
|
||||
def test_assert_extension_array_equal_non_extension_array(side):
|
||||
numpy_array = np.arange(5)
|
||||
extension_array = SparseArray(numpy_array)
|
||||
|
||||
msg = f"{side} is not an ExtensionArray"
|
||||
args = (
|
||||
(numpy_array, extension_array)
|
||||
if side == "left"
|
||||
else (extension_array, numpy_array)
|
||||
)
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_extension_array_equal(*args)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("right_dtype", ["Int32", "int64"])
|
||||
def test_assert_extension_array_equal_ignore_dtype_mismatch(right_dtype):
|
||||
# https://github.com/pandas-dev/pandas/issues/35715
|
||||
left = array([1, 2, 3], dtype="Int64")
|
||||
right = array([1, 2, 3], dtype=right_dtype)
|
||||
tm.assert_extension_array_equal(left, right, check_dtype=False)
|
||||
|
||||
|
||||
def test_assert_extension_array_equal_time_units():
|
||||
# https://github.com/pandas-dev/pandas/issues/55730
|
||||
timestamp = Timestamp("2023-11-04T12")
|
||||
naive = array([timestamp], dtype="datetime64[ns]")
|
||||
utc = array([timestamp], dtype="datetime64[ns, UTC]")
|
||||
|
||||
tm.assert_extension_array_equal(naive, utc, check_dtype=False)
|
||||
tm.assert_extension_array_equal(utc, naive, check_dtype=False)
|
@ -0,0 +1,393 @@
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import DataFrame
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
@pytest.fixture(params=[True, False])
|
||||
def by_blocks_fixture(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(params=["DataFrame", "Series"])
|
||||
def obj_fixture(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def _assert_frame_equal_both(a, b, **kwargs):
|
||||
"""
|
||||
Check that two DataFrame equal.
|
||||
|
||||
This check is performed commutatively.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a : DataFrame
|
||||
The first DataFrame to compare.
|
||||
b : DataFrame
|
||||
The second DataFrame to compare.
|
||||
kwargs : dict
|
||||
The arguments passed to `tm.assert_frame_equal`.
|
||||
"""
|
||||
tm.assert_frame_equal(a, b, **kwargs)
|
||||
tm.assert_frame_equal(b, a, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("check_like", [True, False])
|
||||
def test_frame_equal_row_order_mismatch(check_like, obj_fixture):
|
||||
df1 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index=["a", "b", "c"])
|
||||
df2 = DataFrame({"A": [3, 2, 1], "B": [6, 5, 4]}, index=["c", "b", "a"])
|
||||
|
||||
if not check_like: # Do not ignore row-column orderings.
|
||||
msg = f"{obj_fixture}.index are different"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2, check_like=check_like, obj=obj_fixture)
|
||||
else:
|
||||
_assert_frame_equal_both(df1, df2, check_like=check_like, obj=obj_fixture)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"df1,df2",
|
||||
[
|
||||
(DataFrame({"A": [1, 2, 3]}), DataFrame({"A": [1, 2, 3, 4]})),
|
||||
(DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}), DataFrame({"A": [1, 2, 3]})),
|
||||
],
|
||||
)
|
||||
def test_frame_equal_shape_mismatch(df1, df2, obj_fixture):
|
||||
msg = f"{obj_fixture} are different"
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2, obj=obj_fixture)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"df1,df2,msg",
|
||||
[
|
||||
# Index
|
||||
(
|
||||
DataFrame.from_records({"a": [1, 2], "c": ["l1", "l2"]}, index=["a"]),
|
||||
DataFrame.from_records({"a": [1.0, 2.0], "c": ["l1", "l2"]}, index=["a"]),
|
||||
"DataFrame\\.index are different",
|
||||
),
|
||||
# MultiIndex
|
||||
(
|
||||
DataFrame.from_records(
|
||||
{"a": [1, 2], "b": [2.1, 1.5], "c": ["l1", "l2"]}, index=["a", "b"]
|
||||
),
|
||||
DataFrame.from_records(
|
||||
{"a": [1.0, 2.0], "b": [2.1, 1.5], "c": ["l1", "l2"]}, index=["a", "b"]
|
||||
),
|
||||
"MultiIndex level \\[0\\] are different",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_frame_equal_index_dtype_mismatch(df1, df2, msg, check_index_type):
|
||||
kwargs = {"check_index_type": check_index_type}
|
||||
|
||||
if check_index_type:
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2, **kwargs)
|
||||
else:
|
||||
tm.assert_frame_equal(df1, df2, **kwargs)
|
||||
|
||||
|
||||
def test_empty_dtypes(check_dtype):
|
||||
columns = ["col1", "col2"]
|
||||
df1 = DataFrame(columns=columns)
|
||||
df2 = DataFrame(columns=columns)
|
||||
|
||||
kwargs = {"check_dtype": check_dtype}
|
||||
df1["col1"] = df1["col1"].astype("int64")
|
||||
|
||||
if check_dtype:
|
||||
msg = r"Attributes of DataFrame\..* are different"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2, **kwargs)
|
||||
else:
|
||||
tm.assert_frame_equal(df1, df2, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("check_like", [True, False])
|
||||
def test_frame_equal_index_mismatch(check_like, obj_fixture, using_infer_string):
|
||||
if using_infer_string:
|
||||
dtype = "string"
|
||||
else:
|
||||
dtype = "object"
|
||||
msg = f"""{obj_fixture}\\.index are different
|
||||
|
||||
{obj_fixture}\\.index values are different \\(33\\.33333 %\\)
|
||||
\\[left\\]: Index\\(\\['a', 'b', 'c'\\], dtype='{dtype}'\\)
|
||||
\\[right\\]: Index\\(\\['a', 'b', 'd'\\], dtype='{dtype}'\\)
|
||||
At positional index 2, first diff: c != d"""
|
||||
|
||||
df1 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index=["a", "b", "c"])
|
||||
df2 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index=["a", "b", "d"])
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2, check_like=check_like, obj=obj_fixture)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("check_like", [True, False])
|
||||
def test_frame_equal_columns_mismatch(check_like, obj_fixture, using_infer_string):
|
||||
if using_infer_string:
|
||||
dtype = "string"
|
||||
else:
|
||||
dtype = "object"
|
||||
msg = f"""{obj_fixture}\\.columns are different
|
||||
|
||||
{obj_fixture}\\.columns values are different \\(50\\.0 %\\)
|
||||
\\[left\\]: Index\\(\\['A', 'B'\\], dtype='{dtype}'\\)
|
||||
\\[right\\]: Index\\(\\['A', 'b'\\], dtype='{dtype}'\\)"""
|
||||
|
||||
df1 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index=["a", "b", "c"])
|
||||
df2 = DataFrame({"A": [1, 2, 3], "b": [4, 5, 6]}, index=["a", "b", "c"])
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2, check_like=check_like, obj=obj_fixture)
|
||||
|
||||
|
||||
def test_frame_equal_block_mismatch(by_blocks_fixture, obj_fixture):
|
||||
obj = obj_fixture
|
||||
msg = f"""{obj}\\.iloc\\[:, 1\\] \\(column name="B"\\) are different
|
||||
|
||||
{obj}\\.iloc\\[:, 1\\] \\(column name="B"\\) values are different \\(33\\.33333 %\\)
|
||||
\\[index\\]: \\[0, 1, 2\\]
|
||||
\\[left\\]: \\[4, 5, 6\\]
|
||||
\\[right\\]: \\[4, 5, 7\\]"""
|
||||
|
||||
df1 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
|
||||
df2 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 7]})
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2, by_blocks=by_blocks_fixture, obj=obj_fixture)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"df1,df2,msg",
|
||||
[
|
||||
(
|
||||
DataFrame({"A": ["á", "à", "ä"], "E": ["é", "è", "ë"]}),
|
||||
DataFrame({"A": ["á", "à", "ä"], "E": ["é", "è", "e̊"]}),
|
||||
"""{obj}\\.iloc\\[:, 1\\] \\(column name="E"\\) are different
|
||||
|
||||
{obj}\\.iloc\\[:, 1\\] \\(column name="E"\\) values are different \\(33\\.33333 %\\)
|
||||
\\[index\\]: \\[0, 1, 2\\]
|
||||
\\[left\\]: \\[é, è, ë\\]
|
||||
\\[right\\]: \\[é, è, e̊\\]""",
|
||||
),
|
||||
(
|
||||
DataFrame({"A": ["á", "à", "ä"], "E": ["é", "è", "ë"]}),
|
||||
DataFrame({"A": ["a", "a", "a"], "E": ["e", "e", "e"]}),
|
||||
"""{obj}\\.iloc\\[:, 0\\] \\(column name="A"\\) are different
|
||||
|
||||
{obj}\\.iloc\\[:, 0\\] \\(column name="A"\\) values are different \\(100\\.0 %\\)
|
||||
\\[index\\]: \\[0, 1, 2\\]
|
||||
\\[left\\]: \\[á, à, ä\\]
|
||||
\\[right\\]: \\[a, a, a\\]""",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_frame_equal_unicode(df1, df2, msg, by_blocks_fixture, obj_fixture):
|
||||
# see gh-20503
|
||||
#
|
||||
# Test ensures that `tm.assert_frame_equals` raises the right exception
|
||||
# when comparing DataFrames containing differing unicode objects.
|
||||
msg = msg.format(obj=obj_fixture)
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2, by_blocks=by_blocks_fixture, obj=obj_fixture)
|
||||
|
||||
|
||||
def test_assert_frame_equal_extension_dtype_mismatch():
|
||||
# https://github.com/pandas-dev/pandas/issues/32747
|
||||
left = DataFrame({"a": [1, 2, 3]}, dtype="Int64")
|
||||
right = left.astype(int)
|
||||
|
||||
msg = (
|
||||
"Attributes of DataFrame\\.iloc\\[:, 0\\] "
|
||||
'\\(column name="a"\\) are different\n\n'
|
||||
'Attribute "dtype" are different\n'
|
||||
"\\[left\\]: Int64\n"
|
||||
"\\[right\\]: int[32|64]"
|
||||
)
|
||||
|
||||
tm.assert_frame_equal(left, right, check_dtype=False)
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(left, right, check_dtype=True)
|
||||
|
||||
|
||||
def test_assert_frame_equal_interval_dtype_mismatch():
|
||||
# https://github.com/pandas-dev/pandas/issues/32747
|
||||
left = DataFrame({"a": [pd.Interval(0, 1)]}, dtype="interval")
|
||||
right = left.astype(object)
|
||||
|
||||
msg = (
|
||||
"Attributes of DataFrame\\.iloc\\[:, 0\\] "
|
||||
'\\(column name="a"\\) are different\n\n'
|
||||
'Attribute "dtype" are different\n'
|
||||
"\\[left\\]: interval\\[int64, right\\]\n"
|
||||
"\\[right\\]: object"
|
||||
)
|
||||
|
||||
tm.assert_frame_equal(left, right, check_dtype=False)
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(left, right, check_dtype=True)
|
||||
|
||||
|
||||
def test_assert_frame_equal_ignore_extension_dtype_mismatch():
|
||||
# https://github.com/pandas-dev/pandas/issues/35715
|
||||
left = DataFrame({"a": [1, 2, 3]}, dtype="Int64")
|
||||
right = DataFrame({"a": [1, 2, 3]}, dtype="Int32")
|
||||
tm.assert_frame_equal(left, right, check_dtype=False)
|
||||
|
||||
|
||||
def test_assert_frame_equal_ignore_extension_dtype_mismatch_cross_class():
|
||||
# https://github.com/pandas-dev/pandas/issues/35715
|
||||
left = DataFrame({"a": [1, 2, 3]}, dtype="Int64")
|
||||
right = DataFrame({"a": [1, 2, 3]}, dtype="int64")
|
||||
tm.assert_frame_equal(left, right, check_dtype=False)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"dtype",
|
||||
[
|
||||
("timedelta64[ns]"),
|
||||
("datetime64[ns, UTC]"),
|
||||
("Period[D]"),
|
||||
],
|
||||
)
|
||||
def test_assert_frame_equal_datetime_like_dtype_mismatch(dtype):
|
||||
df1 = DataFrame({"a": []}, dtype=dtype)
|
||||
df2 = DataFrame({"a": []})
|
||||
tm.assert_frame_equal(df1, df2, check_dtype=False)
|
||||
|
||||
|
||||
def test_allows_duplicate_labels():
|
||||
left = DataFrame()
|
||||
right = DataFrame().set_flags(allows_duplicate_labels=False)
|
||||
tm.assert_frame_equal(left, left)
|
||||
tm.assert_frame_equal(right, right)
|
||||
tm.assert_frame_equal(left, right, check_flags=False)
|
||||
tm.assert_frame_equal(right, left, check_flags=False)
|
||||
|
||||
with pytest.raises(AssertionError, match="<Flags"):
|
||||
tm.assert_frame_equal(left, right)
|
||||
|
||||
with pytest.raises(AssertionError, match="<Flags"):
|
||||
tm.assert_frame_equal(left, right)
|
||||
|
||||
|
||||
def test_assert_frame_equal_columns_mixed_dtype():
|
||||
# GH#39168
|
||||
df = DataFrame([[0, 1, 2]], columns=["foo", "bar", 42], index=[1, "test", 2])
|
||||
tm.assert_frame_equal(df, df, check_like=True)
|
||||
|
||||
|
||||
def test_frame_equal_extension_dtype(frame_or_series, any_numeric_ea_dtype):
|
||||
# GH#39410
|
||||
obj = frame_or_series([1, 2], dtype=any_numeric_ea_dtype)
|
||||
tm.assert_equal(obj, obj, check_exact=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("indexer", [(0, 1), (1, 0)])
|
||||
def test_frame_equal_mixed_dtypes(frame_or_series, any_numeric_ea_dtype, indexer):
|
||||
dtypes = (any_numeric_ea_dtype, "int64")
|
||||
obj1 = frame_or_series([1, 2], dtype=dtypes[indexer[0]])
|
||||
obj2 = frame_or_series([1, 2], dtype=dtypes[indexer[1]])
|
||||
tm.assert_equal(obj1, obj2, check_exact=True, check_dtype=False)
|
||||
|
||||
|
||||
def test_assert_frame_equal_check_like_different_indexes():
|
||||
# GH#39739
|
||||
df1 = DataFrame(index=pd.Index([], dtype="object"))
|
||||
df2 = DataFrame(index=pd.RangeIndex(start=0, stop=0, step=1))
|
||||
with pytest.raises(AssertionError, match="DataFrame.index are different"):
|
||||
tm.assert_frame_equal(df1, df2, check_like=True)
|
||||
|
||||
|
||||
def test_assert_frame_equal_checking_allow_dups_flag():
|
||||
# GH#45554
|
||||
left = DataFrame([[1, 2], [3, 4]])
|
||||
left.flags.allows_duplicate_labels = False
|
||||
|
||||
right = DataFrame([[1, 2], [3, 4]])
|
||||
right.flags.allows_duplicate_labels = True
|
||||
tm.assert_frame_equal(left, right, check_flags=False)
|
||||
|
||||
with pytest.raises(AssertionError, match="allows_duplicate_labels"):
|
||||
tm.assert_frame_equal(left, right, check_flags=True)
|
||||
|
||||
|
||||
def test_assert_frame_equal_check_like_categorical_midx():
|
||||
# GH#48975
|
||||
left = DataFrame(
|
||||
[[1], [2], [3]],
|
||||
index=pd.MultiIndex.from_arrays(
|
||||
[
|
||||
pd.Categorical(["a", "b", "c"]),
|
||||
pd.Categorical(["a", "b", "c"]),
|
||||
]
|
||||
),
|
||||
)
|
||||
right = DataFrame(
|
||||
[[3], [2], [1]],
|
||||
index=pd.MultiIndex.from_arrays(
|
||||
[
|
||||
pd.Categorical(["c", "b", "a"]),
|
||||
pd.Categorical(["c", "b", "a"]),
|
||||
]
|
||||
),
|
||||
)
|
||||
tm.assert_frame_equal(left, right, check_like=True)
|
||||
|
||||
|
||||
def test_assert_frame_equal_ea_column_definition_in_exception_mask():
|
||||
# GH#50323
|
||||
df1 = DataFrame({"a": pd.Series([pd.NA, 1], dtype="Int64")})
|
||||
df2 = DataFrame({"a": pd.Series([1, 1], dtype="Int64")})
|
||||
|
||||
msg = r'DataFrame.iloc\[:, 0\] \(column name="a"\) NA mask values are different'
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2)
|
||||
|
||||
|
||||
def test_assert_frame_equal_ea_column_definition_in_exception():
|
||||
# GH#50323
|
||||
df1 = DataFrame({"a": pd.Series([pd.NA, 1], dtype="Int64")})
|
||||
df2 = DataFrame({"a": pd.Series([pd.NA, 2], dtype="Int64")})
|
||||
|
||||
msg = r'DataFrame.iloc\[:, 0\] \(column name="a"\) values are different'
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2)
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2, check_exact=True)
|
||||
|
||||
|
||||
def test_assert_frame_equal_ts_column():
|
||||
# GH#50323
|
||||
df1 = DataFrame({"a": [pd.Timestamp("2019-12-31"), pd.Timestamp("2020-12-31")]})
|
||||
df2 = DataFrame({"a": [pd.Timestamp("2020-12-31"), pd.Timestamp("2020-12-31")]})
|
||||
|
||||
msg = r'DataFrame.iloc\[:, 0\] \(column name="a"\) values are different'
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2)
|
||||
|
||||
|
||||
def test_assert_frame_equal_set():
|
||||
# GH#51727
|
||||
df1 = DataFrame({"set_column": [{1, 2, 3}, {4, 5, 6}]})
|
||||
df2 = DataFrame({"set_column": [{1, 2, 3}, {4, 5, 6}]})
|
||||
tm.assert_frame_equal(df1, df2)
|
||||
|
||||
|
||||
def test_assert_frame_equal_set_mismatch():
|
||||
# GH#51727
|
||||
df1 = DataFrame({"set_column": [{1, 2, 3}, {4, 5, 6}]})
|
||||
df2 = DataFrame({"set_column": [{1, 2, 3}, {4, 5, 7}]})
|
||||
|
||||
msg = r'DataFrame.iloc\[:, 0\] \(column name="set_column"\) values are different'
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_frame_equal(df1, df2)
|
@ -0,0 +1,319 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
NA,
|
||||
Categorical,
|
||||
CategoricalIndex,
|
||||
Index,
|
||||
MultiIndex,
|
||||
NaT,
|
||||
RangeIndex,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def test_index_equal_levels_mismatch():
|
||||
msg = """Index are different
|
||||
|
||||
Index levels are different
|
||||
\\[left\\]: 1, Index\\(\\[1, 2, 3\\], dtype='int64'\\)
|
||||
\\[right\\]: 2, MultiIndex\\(\\[\\('A', 1\\),
|
||||
\\('A', 2\\),
|
||||
\\('B', 3\\),
|
||||
\\('B', 4\\)\\],
|
||||
\\)"""
|
||||
|
||||
idx1 = Index([1, 2, 3])
|
||||
idx2 = MultiIndex.from_tuples([("A", 1), ("A", 2), ("B", 3), ("B", 4)])
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2, exact=False)
|
||||
|
||||
|
||||
def test_index_equal_values_mismatch(check_exact):
|
||||
msg = """MultiIndex level \\[1\\] are different
|
||||
|
||||
MultiIndex level \\[1\\] values are different \\(25\\.0 %\\)
|
||||
\\[left\\]: Index\\(\\[2, 2, 3, 4\\], dtype='int64'\\)
|
||||
\\[right\\]: Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)"""
|
||||
|
||||
idx1 = MultiIndex.from_tuples([("A", 2), ("A", 2), ("B", 3), ("B", 4)])
|
||||
idx2 = MultiIndex.from_tuples([("A", 1), ("A", 2), ("B", 3), ("B", 4)])
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2, check_exact=check_exact)
|
||||
|
||||
|
||||
def test_index_equal_length_mismatch(check_exact):
|
||||
msg = """Index are different
|
||||
|
||||
Index length are different
|
||||
\\[left\\]: 3, Index\\(\\[1, 2, 3\\], dtype='int64'\\)
|
||||
\\[right\\]: 4, Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)"""
|
||||
|
||||
idx1 = Index([1, 2, 3])
|
||||
idx2 = Index([1, 2, 3, 4])
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2, check_exact=check_exact)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exact", [False, "equiv"])
|
||||
def test_index_equal_class(exact):
|
||||
idx1 = Index([0, 1, 2])
|
||||
idx2 = RangeIndex(3)
|
||||
|
||||
tm.assert_index_equal(idx1, idx2, exact=exact)
|
||||
|
||||
|
||||
def test_int_float_index_equal_class_mismatch(check_exact):
|
||||
msg = """Index are different
|
||||
|
||||
Attribute "inferred_type" are different
|
||||
\\[left\\]: integer
|
||||
\\[right\\]: floating"""
|
||||
|
||||
idx1 = Index([1, 2, 3])
|
||||
idx2 = Index([1, 2, 3], dtype=np.float64)
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2, exact=True, check_exact=check_exact)
|
||||
|
||||
|
||||
def test_range_index_equal_class_mismatch(check_exact):
|
||||
msg = """Index are different
|
||||
|
||||
Index classes are different
|
||||
\\[left\\]: Index\\(\\[1, 2, 3\\], dtype='int64'\\)
|
||||
\\[right\\]: """
|
||||
|
||||
idx1 = Index([1, 2, 3])
|
||||
idx2 = RangeIndex(range(3))
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2, exact=True, check_exact=check_exact)
|
||||
|
||||
|
||||
def test_index_equal_values_close(check_exact):
|
||||
idx1 = Index([1, 2, 3.0])
|
||||
idx2 = Index([1, 2, 3.0000000001])
|
||||
|
||||
if check_exact:
|
||||
msg = """Index are different
|
||||
|
||||
Index values are different \\(33\\.33333 %\\)
|
||||
\\[left\\]: Index\\(\\[1.0, 2.0, 3.0], dtype='float64'\\)
|
||||
\\[right\\]: Index\\(\\[1.0, 2.0, 3.0000000001\\], dtype='float64'\\)"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2, check_exact=check_exact)
|
||||
else:
|
||||
tm.assert_index_equal(idx1, idx2, check_exact=check_exact)
|
||||
|
||||
|
||||
def test_index_equal_values_less_close(check_exact, rtol):
|
||||
idx1 = Index([1, 2, 3.0])
|
||||
idx2 = Index([1, 2, 3.0001])
|
||||
kwargs = {"check_exact": check_exact, "rtol": rtol}
|
||||
|
||||
if check_exact or rtol < 0.5e-3:
|
||||
msg = """Index are different
|
||||
|
||||
Index values are different \\(33\\.33333 %\\)
|
||||
\\[left\\]: Index\\(\\[1.0, 2.0, 3.0], dtype='float64'\\)
|
||||
\\[right\\]: Index\\(\\[1.0, 2.0, 3.0001\\], dtype='float64'\\)"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2, **kwargs)
|
||||
else:
|
||||
tm.assert_index_equal(idx1, idx2, **kwargs)
|
||||
|
||||
|
||||
def test_index_equal_values_too_far(check_exact, rtol):
|
||||
idx1 = Index([1, 2, 3])
|
||||
idx2 = Index([1, 2, 4])
|
||||
kwargs = {"check_exact": check_exact, "rtol": rtol}
|
||||
|
||||
msg = """Index are different
|
||||
|
||||
Index values are different \\(33\\.33333 %\\)
|
||||
\\[left\\]: Index\\(\\[1, 2, 3\\], dtype='int64'\\)
|
||||
\\[right\\]: Index\\(\\[1, 2, 4\\], dtype='int64'\\)"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("check_order", [True, False])
|
||||
def test_index_equal_value_order_mismatch(check_exact, rtol, check_order):
|
||||
idx1 = Index([1, 2, 3])
|
||||
idx2 = Index([3, 2, 1])
|
||||
|
||||
msg = """Index are different
|
||||
|
||||
Index values are different \\(66\\.66667 %\\)
|
||||
\\[left\\]: Index\\(\\[1, 2, 3\\], dtype='int64'\\)
|
||||
\\[right\\]: Index\\(\\[3, 2, 1\\], dtype='int64'\\)"""
|
||||
|
||||
if check_order:
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(
|
||||
idx1, idx2, check_exact=check_exact, rtol=rtol, check_order=True
|
||||
)
|
||||
else:
|
||||
tm.assert_index_equal(
|
||||
idx1, idx2, check_exact=check_exact, rtol=rtol, check_order=False
|
||||
)
|
||||
|
||||
|
||||
def test_index_equal_level_values_mismatch(check_exact, rtol):
|
||||
idx1 = MultiIndex.from_tuples([("A", 2), ("A", 2), ("B", 3), ("B", 4)])
|
||||
idx2 = MultiIndex.from_tuples([("A", 1), ("A", 2), ("B", 3), ("B", 4)])
|
||||
kwargs = {"check_exact": check_exact, "rtol": rtol}
|
||||
|
||||
msg = """MultiIndex level \\[1\\] are different
|
||||
|
||||
MultiIndex level \\[1\\] values are different \\(25\\.0 %\\)
|
||||
\\[left\\]: Index\\(\\[2, 2, 3, 4\\], dtype='int64'\\)
|
||||
\\[right\\]: Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"name1,name2",
|
||||
[(None, "x"), ("x", "x"), (np.nan, np.nan), (NaT, NaT), (np.nan, NaT)],
|
||||
)
|
||||
def test_index_equal_names(name1, name2):
|
||||
idx1 = Index([1, 2, 3], name=name1)
|
||||
idx2 = Index([1, 2, 3], name=name2)
|
||||
|
||||
if name1 == name2 or name1 is name2:
|
||||
tm.assert_index_equal(idx1, idx2)
|
||||
else:
|
||||
name1 = "'x'" if name1 == "x" else name1
|
||||
name2 = "'x'" if name2 == "x" else name2
|
||||
msg = f"""Index are different
|
||||
|
||||
Attribute "names" are different
|
||||
\\[left\\]: \\[{name1}\\]
|
||||
\\[right\\]: \\[{name2}\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2)
|
||||
|
||||
|
||||
def test_index_equal_category_mismatch(check_categorical, using_infer_string):
|
||||
if using_infer_string:
|
||||
dtype = "string"
|
||||
else:
|
||||
dtype = "object"
|
||||
msg = f"""Index are different
|
||||
|
||||
Attribute "dtype" are different
|
||||
\\[left\\]: CategoricalDtype\\(categories=\\['a', 'b'\\], ordered=False, \
|
||||
categories_dtype={dtype}\\)
|
||||
\\[right\\]: CategoricalDtype\\(categories=\\['a', 'b', 'c'\\], \
|
||||
ordered=False, categories_dtype={dtype}\\)"""
|
||||
|
||||
idx1 = Index(Categorical(["a", "b"]))
|
||||
idx2 = Index(Categorical(["a", "b"], categories=["a", "b", "c"]))
|
||||
|
||||
if check_categorical:
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2, check_categorical=check_categorical)
|
||||
else:
|
||||
tm.assert_index_equal(idx1, idx2, check_categorical=check_categorical)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exact", [False, True])
|
||||
def test_index_equal_range_categories(check_categorical, exact):
|
||||
# GH41263
|
||||
msg = """\
|
||||
Index are different
|
||||
|
||||
Index classes are different
|
||||
\\[left\\]: RangeIndex\\(start=0, stop=10, step=1\\)
|
||||
\\[right\\]: Index\\(\\[0, 1, 2, 3, 4, 5, 6, 7, 8, 9\\], dtype='int64'\\)"""
|
||||
|
||||
rcat = CategoricalIndex(RangeIndex(10))
|
||||
icat = CategoricalIndex(list(range(10)))
|
||||
|
||||
if check_categorical and exact:
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(rcat, icat, check_categorical=True, exact=True)
|
||||
else:
|
||||
tm.assert_index_equal(
|
||||
rcat, icat, check_categorical=check_categorical, exact=exact
|
||||
)
|
||||
|
||||
|
||||
def test_assert_index_equal_different_inferred_types():
|
||||
# GH#31884
|
||||
msg = """\
|
||||
Index are different
|
||||
|
||||
Attribute "inferred_type" are different
|
||||
\\[left\\]: mixed
|
||||
\\[right\\]: datetime"""
|
||||
|
||||
idx1 = Index([NA, np.datetime64("nat")])
|
||||
idx2 = Index([NA, NaT])
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_index_equal(idx1, idx2)
|
||||
|
||||
|
||||
def test_assert_index_equal_different_names_check_order_false():
|
||||
# GH#47328
|
||||
idx1 = Index([1, 3], name="a")
|
||||
idx2 = Index([3, 1], name="b")
|
||||
with pytest.raises(AssertionError, match='"names" are different'):
|
||||
tm.assert_index_equal(idx1, idx2, check_order=False, check_names=True)
|
||||
|
||||
|
||||
def test_assert_index_equal_mixed_dtype():
|
||||
# GH#39168
|
||||
idx = Index(["foo", "bar", 42])
|
||||
tm.assert_index_equal(idx, idx, check_order=False)
|
||||
|
||||
|
||||
def test_assert_index_equal_ea_dtype_order_false(any_numeric_ea_dtype):
|
||||
# GH#47207
|
||||
idx1 = Index([1, 3], dtype=any_numeric_ea_dtype)
|
||||
idx2 = Index([3, 1], dtype=any_numeric_ea_dtype)
|
||||
tm.assert_index_equal(idx1, idx2, check_order=False)
|
||||
|
||||
|
||||
def test_assert_index_equal_object_ints_order_false():
|
||||
# GH#47207
|
||||
idx1 = Index([1, 3], dtype="object")
|
||||
idx2 = Index([3, 1], dtype="object")
|
||||
tm.assert_index_equal(idx1, idx2, check_order=False)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("check_categorical", [True, False])
|
||||
@pytest.mark.parametrize("check_names", [True, False])
|
||||
def test_assert_ea_index_equal_non_matching_na(check_names, check_categorical):
|
||||
# GH#48608
|
||||
idx1 = Index([1, 2], dtype="Int64")
|
||||
idx2 = Index([1, NA], dtype="Int64")
|
||||
with pytest.raises(AssertionError, match="50.0 %"):
|
||||
tm.assert_index_equal(
|
||||
idx1, idx2, check_names=check_names, check_categorical=check_categorical
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("check_categorical", [True, False])
|
||||
def test_assert_multi_index_dtype_check_categorical(check_categorical):
|
||||
# GH#52126
|
||||
idx1 = MultiIndex.from_arrays([Categorical(np.array([1, 2], dtype=np.uint64))])
|
||||
idx2 = MultiIndex.from_arrays([Categorical(np.array([1, 2], dtype=np.int64))])
|
||||
if check_categorical:
|
||||
with pytest.raises(
|
||||
AssertionError, match=r"^MultiIndex level \[0\] are different"
|
||||
):
|
||||
tm.assert_index_equal(idx1, idx2, check_categorical=check_categorical)
|
||||
else:
|
||||
tm.assert_index_equal(idx1, idx2, check_categorical=check_categorical)
|
@ -0,0 +1,81 @@
|
||||
import pytest
|
||||
|
||||
from pandas import interval_range
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"kwargs",
|
||||
[
|
||||
{"start": 0, "periods": 4},
|
||||
{"start": 1, "periods": 5},
|
||||
{"start": 5, "end": 10, "closed": "left"},
|
||||
],
|
||||
)
|
||||
def test_interval_array_equal(kwargs):
|
||||
arr = interval_range(**kwargs).values
|
||||
tm.assert_interval_array_equal(arr, arr)
|
||||
|
||||
|
||||
def test_interval_array_equal_closed_mismatch():
|
||||
kwargs = {"start": 0, "periods": 5}
|
||||
arr1 = interval_range(closed="left", **kwargs).values
|
||||
arr2 = interval_range(closed="right", **kwargs).values
|
||||
|
||||
msg = """\
|
||||
IntervalArray are different
|
||||
|
||||
Attribute "closed" are different
|
||||
\\[left\\]: left
|
||||
\\[right\\]: right"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_interval_array_equal(arr1, arr2)
|
||||
|
||||
|
||||
def test_interval_array_equal_periods_mismatch():
|
||||
kwargs = {"start": 0}
|
||||
arr1 = interval_range(periods=5, **kwargs).values
|
||||
arr2 = interval_range(periods=6, **kwargs).values
|
||||
|
||||
msg = """\
|
||||
IntervalArray.left are different
|
||||
|
||||
IntervalArray.left shapes are different
|
||||
\\[left\\]: \\(5,\\)
|
||||
\\[right\\]: \\(6,\\)"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_interval_array_equal(arr1, arr2)
|
||||
|
||||
|
||||
def test_interval_array_equal_end_mismatch():
|
||||
kwargs = {"start": 0, "periods": 5}
|
||||
arr1 = interval_range(end=10, **kwargs).values
|
||||
arr2 = interval_range(end=20, **kwargs).values
|
||||
|
||||
msg = """\
|
||||
IntervalArray.left are different
|
||||
|
||||
IntervalArray.left values are different \\(80.0 %\\)
|
||||
\\[left\\]: \\[0, 2, 4, 6, 8\\]
|
||||
\\[right\\]: \\[0, 4, 8, 12, 16\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_interval_array_equal(arr1, arr2)
|
||||
|
||||
|
||||
def test_interval_array_equal_start_mismatch():
|
||||
kwargs = {"periods": 4}
|
||||
arr1 = interval_range(start=0, **kwargs).values
|
||||
arr2 = interval_range(start=1, **kwargs).values
|
||||
|
||||
msg = """\
|
||||
IntervalArray.left are different
|
||||
|
||||
IntervalArray.left values are different \\(100.0 %\\)
|
||||
\\[left\\]: \\[0, 1, 2, 3\\]
|
||||
\\[right\\]: \\[1, 2, 3, 4\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_interval_array_equal(arr1, arr2)
|
@ -0,0 +1,223 @@
|
||||
import copy
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import Timestamp
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def test_assert_numpy_array_equal_shape_mismatch():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array shapes are different
|
||||
\\[left\\]: \\(2L*,\\)
|
||||
\\[right\\]: \\(3L*,\\)"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(np.array([1, 2]), np.array([3, 4, 5]))
|
||||
|
||||
|
||||
def test_assert_numpy_array_equal_bad_type():
|
||||
expected = "Expected type"
|
||||
|
||||
with pytest.raises(AssertionError, match=expected):
|
||||
tm.assert_numpy_array_equal(1, 2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"a,b,klass1,klass2",
|
||||
[(np.array([1]), 1, "ndarray", "int"), (1, np.array([1]), "int", "ndarray")],
|
||||
)
|
||||
def test_assert_numpy_array_equal_class_mismatch(a, b, klass1, klass2):
|
||||
msg = f"""numpy array are different
|
||||
|
||||
numpy array classes are different
|
||||
\\[left\\]: {klass1}
|
||||
\\[right\\]: {klass2}"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(a, b)
|
||||
|
||||
|
||||
def test_assert_numpy_array_equal_value_mismatch1():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(66\\.66667 %\\)
|
||||
\\[left\\]: \\[nan, 2\\.0, 3\\.0\\]
|
||||
\\[right\\]: \\[1\\.0, nan, 3\\.0\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(np.array([np.nan, 2, 3]), np.array([1, np.nan, 3]))
|
||||
|
||||
|
||||
def test_assert_numpy_array_equal_value_mismatch2():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(50\\.0 %\\)
|
||||
\\[left\\]: \\[1, 2\\]
|
||||
\\[right\\]: \\[1, 3\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(np.array([1, 2]), np.array([1, 3]))
|
||||
|
||||
|
||||
def test_assert_numpy_array_equal_value_mismatch3():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(16\\.66667 %\\)
|
||||
\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\], \\[5, 6\\]\\]
|
||||
\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\], \\[5, 6\\]\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(
|
||||
np.array([[1, 2], [3, 4], [5, 6]]), np.array([[1, 3], [3, 4], [5, 6]])
|
||||
)
|
||||
|
||||
|
||||
def test_assert_numpy_array_equal_value_mismatch4():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(50\\.0 %\\)
|
||||
\\[left\\]: \\[1\\.1, 2\\.000001\\]
|
||||
\\[right\\]: \\[1\\.1, 2.0\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(np.array([1.1, 2.000001]), np.array([1.1, 2.0]))
|
||||
|
||||
|
||||
def test_assert_numpy_array_equal_value_mismatch5():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(16\\.66667 %\\)
|
||||
\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\], \\[5, 6\\]\\]
|
||||
\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\], \\[5, 6\\]\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(
|
||||
np.array([[1, 2], [3, 4], [5, 6]]), np.array([[1, 3], [3, 4], [5, 6]])
|
||||
)
|
||||
|
||||
|
||||
def test_assert_numpy_array_equal_value_mismatch6():
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(25\\.0 %\\)
|
||||
\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\]\\]
|
||||
\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\]\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(
|
||||
np.array([[1, 2], [3, 4]]), np.array([[1, 3], [3, 4]])
|
||||
)
|
||||
|
||||
|
||||
def test_assert_numpy_array_equal_shape_mismatch_override():
|
||||
msg = """Index are different
|
||||
|
||||
Index shapes are different
|
||||
\\[left\\]: \\(2L*,\\)
|
||||
\\[right\\]: \\(3L*,\\)"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(np.array([1, 2]), np.array([3, 4, 5]), obj="Index")
|
||||
|
||||
|
||||
def test_numpy_array_equal_unicode():
|
||||
# see gh-20503
|
||||
#
|
||||
# Test ensures that `tm.assert_numpy_array_equals` raises the right
|
||||
# exception when comparing np.arrays containing differing unicode objects.
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(33\\.33333 %\\)
|
||||
\\[left\\]: \\[á, à, ä\\]
|
||||
\\[right\\]: \\[á, à, å\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(
|
||||
np.array(["á", "à", "ä"]), np.array(["á", "à", "å"])
|
||||
)
|
||||
|
||||
|
||||
def test_numpy_array_equal_object():
|
||||
a = np.array([Timestamp("2011-01-01"), Timestamp("2011-01-01")])
|
||||
b = np.array([Timestamp("2011-01-01"), Timestamp("2011-01-02")])
|
||||
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(50\\.0 %\\)
|
||||
\\[left\\]: \\[2011-01-01 00:00:00, 2011-01-01 00:00:00\\]
|
||||
\\[right\\]: \\[2011-01-01 00:00:00, 2011-01-02 00:00:00\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("other_type", ["same", "copy"])
|
||||
@pytest.mark.parametrize("check_same", ["same", "copy"])
|
||||
def test_numpy_array_equal_copy_flag(other_type, check_same):
|
||||
a = np.array([1, 2, 3])
|
||||
msg = None
|
||||
|
||||
if other_type == "same":
|
||||
other = a.view()
|
||||
else:
|
||||
other = a.copy()
|
||||
|
||||
if check_same != other_type:
|
||||
msg = (
|
||||
r"array\(\[1, 2, 3\]\) is not array\(\[1, 2, 3\]\)"
|
||||
if check_same == "same"
|
||||
else r"array\(\[1, 2, 3\]\) is array\(\[1, 2, 3\]\)"
|
||||
)
|
||||
|
||||
if msg is not None:
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(a, other, check_same=check_same)
|
||||
else:
|
||||
tm.assert_numpy_array_equal(a, other, check_same=check_same)
|
||||
|
||||
|
||||
def test_numpy_array_equal_contains_na():
|
||||
# https://github.com/pandas-dev/pandas/issues/31881
|
||||
a = np.array([True, False])
|
||||
b = np.array([True, pd.NA], dtype=object)
|
||||
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(50.0 %\\)
|
||||
\\[left\\]: \\[True, False\\]
|
||||
\\[right\\]: \\[True, <NA>\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(a, b)
|
||||
|
||||
|
||||
def test_numpy_array_equal_identical_na(nulls_fixture):
|
||||
a = np.array([nulls_fixture], dtype=object)
|
||||
|
||||
tm.assert_numpy_array_equal(a, a)
|
||||
|
||||
# matching but not the identical object
|
||||
if hasattr(nulls_fixture, "copy"):
|
||||
other = nulls_fixture.copy()
|
||||
else:
|
||||
other = copy.copy(nulls_fixture)
|
||||
b = np.array([other], dtype=object)
|
||||
tm.assert_numpy_array_equal(a, b)
|
||||
|
||||
|
||||
def test_numpy_array_equal_different_na():
|
||||
a = np.array([np.nan], dtype=object)
|
||||
b = np.array([pd.NA], dtype=object)
|
||||
|
||||
msg = """numpy array are different
|
||||
|
||||
numpy array values are different \\(100.0 %\\)
|
||||
\\[left\\]: \\[nan\\]
|
||||
\\[right\\]: \\[<NA>\\]"""
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_numpy_array_equal(a, b)
|
@ -0,0 +1,241 @@
|
||||
""""
|
||||
Test module for testing ``pandas._testing.assert_produces_warning``.
|
||||
"""
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
|
||||
from pandas.errors import (
|
||||
DtypeWarning,
|
||||
PerformanceWarning,
|
||||
)
|
||||
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
params=[
|
||||
RuntimeWarning,
|
||||
ResourceWarning,
|
||||
UserWarning,
|
||||
FutureWarning,
|
||||
DeprecationWarning,
|
||||
PerformanceWarning,
|
||||
DtypeWarning,
|
||||
],
|
||||
)
|
||||
def category(request):
|
||||
"""
|
||||
Return unique warning.
|
||||
|
||||
Useful for testing behavior of tm.assert_produces_warning with various categories.
|
||||
"""
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
params=[
|
||||
(RuntimeWarning, UserWarning),
|
||||
(UserWarning, FutureWarning),
|
||||
(FutureWarning, RuntimeWarning),
|
||||
(DeprecationWarning, PerformanceWarning),
|
||||
(PerformanceWarning, FutureWarning),
|
||||
(DtypeWarning, DeprecationWarning),
|
||||
(ResourceWarning, DeprecationWarning),
|
||||
(FutureWarning, DeprecationWarning),
|
||||
],
|
||||
ids=lambda x: type(x).__name__,
|
||||
)
|
||||
def pair_different_warnings(request):
|
||||
"""
|
||||
Return pair or different warnings.
|
||||
|
||||
Useful for testing how several different warnings are handled
|
||||
in tm.assert_produces_warning.
|
||||
"""
|
||||
return request.param
|
||||
|
||||
|
||||
def f():
|
||||
warnings.warn("f1", FutureWarning)
|
||||
warnings.warn("f2", RuntimeWarning)
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:f1:FutureWarning")
|
||||
def test_assert_produces_warning_honors_filter():
|
||||
# Raise by default.
|
||||
msg = r"Caused unexpected warning\(s\)"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
with tm.assert_produces_warning(RuntimeWarning):
|
||||
f()
|
||||
|
||||
with tm.assert_produces_warning(RuntimeWarning, raise_on_extra_warnings=False):
|
||||
f()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"message, match",
|
||||
[
|
||||
("", None),
|
||||
("", ""),
|
||||
("Warning message", r".*"),
|
||||
("Warning message", "War"),
|
||||
("Warning message", r"[Ww]arning"),
|
||||
("Warning message", "age"),
|
||||
("Warning message", r"age$"),
|
||||
("Message 12-234 with numbers", r"\d{2}-\d{3}"),
|
||||
("Message 12-234 with numbers", r"^Mes.*\d{2}-\d{3}"),
|
||||
("Message 12-234 with numbers", r"\d{2}-\d{3}\s\S+"),
|
||||
("Message, which we do not match", None),
|
||||
],
|
||||
)
|
||||
def test_catch_warning_category_and_match(category, message, match):
|
||||
with tm.assert_produces_warning(category, match=match):
|
||||
warnings.warn(message, category)
|
||||
|
||||
|
||||
def test_fail_to_match_runtime_warning():
|
||||
category = RuntimeWarning
|
||||
match = "Did not see this warning"
|
||||
unmatched = (
|
||||
r"Did not see warning 'RuntimeWarning' matching 'Did not see this warning'. "
|
||||
r"The emitted warning messages are "
|
||||
r"\[RuntimeWarning\('This is not a match.'\), "
|
||||
r"RuntimeWarning\('Another unmatched warning.'\)\]"
|
||||
)
|
||||
with pytest.raises(AssertionError, match=unmatched):
|
||||
with tm.assert_produces_warning(category, match=match):
|
||||
warnings.warn("This is not a match.", category)
|
||||
warnings.warn("Another unmatched warning.", category)
|
||||
|
||||
|
||||
def test_fail_to_match_future_warning():
|
||||
category = FutureWarning
|
||||
match = "Warning"
|
||||
unmatched = (
|
||||
r"Did not see warning 'FutureWarning' matching 'Warning'. "
|
||||
r"The emitted warning messages are "
|
||||
r"\[FutureWarning\('This is not a match.'\), "
|
||||
r"FutureWarning\('Another unmatched warning.'\)\]"
|
||||
)
|
||||
with pytest.raises(AssertionError, match=unmatched):
|
||||
with tm.assert_produces_warning(category, match=match):
|
||||
warnings.warn("This is not a match.", category)
|
||||
warnings.warn("Another unmatched warning.", category)
|
||||
|
||||
|
||||
def test_fail_to_match_resource_warning():
|
||||
category = ResourceWarning
|
||||
match = r"\d+"
|
||||
unmatched = (
|
||||
r"Did not see warning 'ResourceWarning' matching '\\d\+'. "
|
||||
r"The emitted warning messages are "
|
||||
r"\[ResourceWarning\('This is not a match.'\), "
|
||||
r"ResourceWarning\('Another unmatched warning.'\)\]"
|
||||
)
|
||||
with pytest.raises(AssertionError, match=unmatched):
|
||||
with tm.assert_produces_warning(category, match=match):
|
||||
warnings.warn("This is not a match.", category)
|
||||
warnings.warn("Another unmatched warning.", category)
|
||||
|
||||
|
||||
def test_fail_to_catch_actual_warning(pair_different_warnings):
|
||||
expected_category, actual_category = pair_different_warnings
|
||||
match = "Did not see expected warning of class"
|
||||
with pytest.raises(AssertionError, match=match):
|
||||
with tm.assert_produces_warning(expected_category):
|
||||
warnings.warn("warning message", actual_category)
|
||||
|
||||
|
||||
def test_ignore_extra_warning(pair_different_warnings):
|
||||
expected_category, extra_category = pair_different_warnings
|
||||
with tm.assert_produces_warning(expected_category, raise_on_extra_warnings=False):
|
||||
warnings.warn("Expected warning", expected_category)
|
||||
warnings.warn("Unexpected warning OK", extra_category)
|
||||
|
||||
|
||||
def test_raise_on_extra_warning(pair_different_warnings):
|
||||
expected_category, extra_category = pair_different_warnings
|
||||
match = r"Caused unexpected warning\(s\)"
|
||||
with pytest.raises(AssertionError, match=match):
|
||||
with tm.assert_produces_warning(expected_category):
|
||||
warnings.warn("Expected warning", expected_category)
|
||||
warnings.warn("Unexpected warning NOT OK", extra_category)
|
||||
|
||||
|
||||
def test_same_category_different_messages_first_match():
|
||||
category = UserWarning
|
||||
with tm.assert_produces_warning(category, match=r"^Match this"):
|
||||
warnings.warn("Match this", category)
|
||||
warnings.warn("Do not match that", category)
|
||||
warnings.warn("Do not match that either", category)
|
||||
|
||||
|
||||
def test_same_category_different_messages_last_match():
|
||||
category = DeprecationWarning
|
||||
with tm.assert_produces_warning(category, match=r"^Match this"):
|
||||
warnings.warn("Do not match that", category)
|
||||
warnings.warn("Do not match that either", category)
|
||||
warnings.warn("Match this", category)
|
||||
|
||||
|
||||
def test_match_multiple_warnings():
|
||||
# https://github.com/pandas-dev/pandas/issues/47829
|
||||
category = (FutureWarning, UserWarning)
|
||||
with tm.assert_produces_warning(category, match=r"^Match this"):
|
||||
warnings.warn("Match this", FutureWarning)
|
||||
warnings.warn("Match this too", UserWarning)
|
||||
|
||||
|
||||
def test_right_category_wrong_match_raises(pair_different_warnings):
|
||||
target_category, other_category = pair_different_warnings
|
||||
with pytest.raises(AssertionError, match="Did not see warning.*matching"):
|
||||
with tm.assert_produces_warning(target_category, match=r"^Match this"):
|
||||
warnings.warn("Do not match it", target_category)
|
||||
warnings.warn("Match this", other_category)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("false_or_none", [False, None])
|
||||
class TestFalseOrNoneExpectedWarning:
|
||||
def test_raise_on_warning(self, false_or_none):
|
||||
msg = r"Caused unexpected warning\(s\)"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
with tm.assert_produces_warning(false_or_none):
|
||||
f()
|
||||
|
||||
def test_no_raise_without_warning(self, false_or_none):
|
||||
with tm.assert_produces_warning(false_or_none):
|
||||
pass
|
||||
|
||||
def test_no_raise_with_false_raise_on_extra(self, false_or_none):
|
||||
with tm.assert_produces_warning(false_or_none, raise_on_extra_warnings=False):
|
||||
f()
|
||||
|
||||
|
||||
def test_raises_during_exception():
|
||||
msg = "Did not see expected warning of class 'UserWarning'"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
with tm.assert_produces_warning(UserWarning):
|
||||
raise ValueError
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
with tm.assert_produces_warning(UserWarning):
|
||||
warnings.warn("FutureWarning", FutureWarning)
|
||||
raise IndexError
|
||||
|
||||
msg = "Caused unexpected warning"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
with tm.assert_produces_warning(None):
|
||||
warnings.warn("FutureWarning", FutureWarning)
|
||||
raise SystemError
|
||||
|
||||
|
||||
def test_passes_during_exception():
|
||||
with pytest.raises(SyntaxError, match="Error"):
|
||||
with tm.assert_produces_warning(None):
|
||||
raise SyntaxError("Error")
|
||||
|
||||
with pytest.raises(ValueError, match="Error"):
|
||||
with tm.assert_produces_warning(FutureWarning, match="FutureWarning"):
|
||||
warnings.warn("FutureWarning", FutureWarning)
|
||||
raise ValueError("Error")
|
@ -0,0 +1,484 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import (
|
||||
Categorical,
|
||||
DataFrame,
|
||||
Series,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def _assert_series_equal_both(a, b, **kwargs):
|
||||
"""
|
||||
Check that two Series equal.
|
||||
|
||||
This check is performed commutatively.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a : Series
|
||||
The first Series to compare.
|
||||
b : Series
|
||||
The second Series to compare.
|
||||
kwargs : dict
|
||||
The arguments passed to `tm.assert_series_equal`.
|
||||
"""
|
||||
tm.assert_series_equal(a, b, **kwargs)
|
||||
tm.assert_series_equal(b, a, **kwargs)
|
||||
|
||||
|
||||
def _assert_not_series_equal(a, b, **kwargs):
|
||||
"""
|
||||
Check that two Series are not equal.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a : Series
|
||||
The first Series to compare.
|
||||
b : Series
|
||||
The second Series to compare.
|
||||
kwargs : dict
|
||||
The arguments passed to `tm.assert_series_equal`.
|
||||
"""
|
||||
try:
|
||||
tm.assert_series_equal(a, b, **kwargs)
|
||||
msg = "The two Series were equal when they shouldn't have been"
|
||||
|
||||
pytest.fail(msg=msg)
|
||||
except AssertionError:
|
||||
pass
|
||||
|
||||
|
||||
def _assert_not_series_equal_both(a, b, **kwargs):
|
||||
"""
|
||||
Check that two Series are not equal.
|
||||
|
||||
This check is performed commutatively.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a : Series
|
||||
The first Series to compare.
|
||||
b : Series
|
||||
The second Series to compare.
|
||||
kwargs : dict
|
||||
The arguments passed to `tm.assert_series_equal`.
|
||||
"""
|
||||
_assert_not_series_equal(a, b, **kwargs)
|
||||
_assert_not_series_equal(b, a, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("data", [range(3), list("abc"), list("áàä")])
|
||||
def test_series_equal(data):
|
||||
_assert_series_equal_both(Series(data), Series(data))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"data1,data2",
|
||||
[
|
||||
(range(3), range(1, 4)),
|
||||
(list("abc"), list("xyz")),
|
||||
(list("áàä"), list("éèë")),
|
||||
(list("áàä"), list(b"aaa")),
|
||||
(range(3), range(4)),
|
||||
],
|
||||
)
|
||||
def test_series_not_equal_value_mismatch(data1, data2):
|
||||
_assert_not_series_equal_both(Series(data1), Series(data2))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"kwargs",
|
||||
[
|
||||
{"dtype": "float64"}, # dtype mismatch
|
||||
{"index": [1, 2, 4]}, # index mismatch
|
||||
{"name": "foo"}, # name mismatch
|
||||
],
|
||||
)
|
||||
def test_series_not_equal_metadata_mismatch(kwargs):
|
||||
data = range(3)
|
||||
s1 = Series(data)
|
||||
|
||||
s2 = Series(data, **kwargs)
|
||||
_assert_not_series_equal_both(s1, s2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("data1,data2", [(0.12345, 0.12346), (0.1235, 0.1236)])
|
||||
@pytest.mark.parametrize("dtype", ["float32", "float64", "Float32"])
|
||||
@pytest.mark.parametrize("decimals", [0, 1, 2, 3, 5, 10])
|
||||
def test_less_precise(data1, data2, dtype, decimals):
|
||||
rtol = 10**-decimals
|
||||
s1 = Series([data1], dtype=dtype)
|
||||
s2 = Series([data2], dtype=dtype)
|
||||
|
||||
if decimals in (5, 10) or (decimals >= 3 and abs(data1 - data2) >= 0.0005):
|
||||
msg = "Series values are different"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(s1, s2, rtol=rtol)
|
||||
else:
|
||||
_assert_series_equal_both(s1, s2, rtol=rtol)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"s1,s2,msg",
|
||||
[
|
||||
# Index
|
||||
(
|
||||
Series(["l1", "l2"], index=[1, 2]),
|
||||
Series(["l1", "l2"], index=[1.0, 2.0]),
|
||||
"Series\\.index are different",
|
||||
),
|
||||
# MultiIndex
|
||||
(
|
||||
DataFrame.from_records(
|
||||
{"a": [1, 2], "b": [2.1, 1.5], "c": ["l1", "l2"]}, index=["a", "b"]
|
||||
).c,
|
||||
DataFrame.from_records(
|
||||
{"a": [1.0, 2.0], "b": [2.1, 1.5], "c": ["l1", "l2"]}, index=["a", "b"]
|
||||
).c,
|
||||
"MultiIndex level \\[0\\] are different",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_series_equal_index_dtype(s1, s2, msg, check_index_type):
|
||||
kwargs = {"check_index_type": check_index_type}
|
||||
|
||||
if check_index_type:
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(s1, s2, **kwargs)
|
||||
else:
|
||||
tm.assert_series_equal(s1, s2, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("check_like", [True, False])
|
||||
def test_series_equal_order_mismatch(check_like):
|
||||
s1 = Series([1, 2, 3], index=["a", "b", "c"])
|
||||
s2 = Series([3, 2, 1], index=["c", "b", "a"])
|
||||
|
||||
if not check_like: # Do not ignore index ordering.
|
||||
with pytest.raises(AssertionError, match="Series.index are different"):
|
||||
tm.assert_series_equal(s1, s2, check_like=check_like)
|
||||
else:
|
||||
_assert_series_equal_both(s1, s2, check_like=check_like)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("check_index", [True, False])
|
||||
def test_series_equal_index_mismatch(check_index):
|
||||
s1 = Series([1, 2, 3], index=["a", "b", "c"])
|
||||
s2 = Series([1, 2, 3], index=["c", "b", "a"])
|
||||
|
||||
if check_index: # Do not ignore index.
|
||||
with pytest.raises(AssertionError, match="Series.index are different"):
|
||||
tm.assert_series_equal(s1, s2, check_index=check_index)
|
||||
else:
|
||||
_assert_series_equal_both(s1, s2, check_index=check_index)
|
||||
|
||||
|
||||
def test_series_invalid_param_combination():
|
||||
left = Series(dtype=object)
|
||||
right = Series(dtype=object)
|
||||
with pytest.raises(
|
||||
ValueError, match="check_like must be False if check_index is False"
|
||||
):
|
||||
tm.assert_series_equal(left, right, check_index=False, check_like=True)
|
||||
|
||||
|
||||
def test_series_equal_length_mismatch(rtol):
|
||||
msg = """Series are different
|
||||
|
||||
Series length are different
|
||||
\\[left\\]: 3, RangeIndex\\(start=0, stop=3, step=1\\)
|
||||
\\[right\\]: 4, RangeIndex\\(start=0, stop=4, step=1\\)"""
|
||||
|
||||
s1 = Series([1, 2, 3])
|
||||
s2 = Series([1, 2, 3, 4])
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(s1, s2, rtol=rtol)
|
||||
|
||||
|
||||
def test_series_equal_numeric_values_mismatch(rtol):
|
||||
msg = """Series are different
|
||||
|
||||
Series values are different \\(33\\.33333 %\\)
|
||||
\\[index\\]: \\[0, 1, 2\\]
|
||||
\\[left\\]: \\[1, 2, 3\\]
|
||||
\\[right\\]: \\[1, 2, 4\\]"""
|
||||
|
||||
s1 = Series([1, 2, 3])
|
||||
s2 = Series([1, 2, 4])
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(s1, s2, rtol=rtol)
|
||||
|
||||
|
||||
def test_series_equal_categorical_values_mismatch(rtol, using_infer_string):
|
||||
if using_infer_string:
|
||||
msg = """Series are different
|
||||
|
||||
Series values are different \\(66\\.66667 %\\)
|
||||
\\[index\\]: \\[0, 1, 2\\]
|
||||
\\[left\\]: \\['a', 'b', 'c'\\]
|
||||
Categories \\(3, string\\): \\[a, b, c\\]
|
||||
\\[right\\]: \\['a', 'c', 'b'\\]
|
||||
Categories \\(3, string\\): \\[a, b, c\\]"""
|
||||
else:
|
||||
msg = """Series are different
|
||||
|
||||
Series values are different \\(66\\.66667 %\\)
|
||||
\\[index\\]: \\[0, 1, 2\\]
|
||||
\\[left\\]: \\['a', 'b', 'c'\\]
|
||||
Categories \\(3, object\\): \\['a', 'b', 'c'\\]
|
||||
\\[right\\]: \\['a', 'c', 'b'\\]
|
||||
Categories \\(3, object\\): \\['a', 'b', 'c'\\]"""
|
||||
|
||||
s1 = Series(Categorical(["a", "b", "c"]))
|
||||
s2 = Series(Categorical(["a", "c", "b"]))
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(s1, s2, rtol=rtol)
|
||||
|
||||
|
||||
def test_series_equal_datetime_values_mismatch(rtol):
|
||||
msg = """Series are different
|
||||
|
||||
Series values are different \\(100.0 %\\)
|
||||
\\[index\\]: \\[0, 1, 2\\]
|
||||
\\[left\\]: \\[1514764800000000000, 1514851200000000000, 1514937600000000000\\]
|
||||
\\[right\\]: \\[1549065600000000000, 1549152000000000000, 1549238400000000000\\]"""
|
||||
|
||||
s1 = Series(pd.date_range("2018-01-01", periods=3, freq="D"))
|
||||
s2 = Series(pd.date_range("2019-02-02", periods=3, freq="D"))
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(s1, s2, rtol=rtol)
|
||||
|
||||
|
||||
def test_series_equal_categorical_mismatch(check_categorical, using_infer_string):
|
||||
if using_infer_string:
|
||||
dtype = "string"
|
||||
else:
|
||||
dtype = "object"
|
||||
msg = f"""Attributes of Series are different
|
||||
|
||||
Attribute "dtype" are different
|
||||
\\[left\\]: CategoricalDtype\\(categories=\\['a', 'b'\\], ordered=False, \
|
||||
categories_dtype={dtype}\\)
|
||||
\\[right\\]: CategoricalDtype\\(categories=\\['a', 'b', 'c'\\], \
|
||||
ordered=False, categories_dtype={dtype}\\)"""
|
||||
|
||||
s1 = Series(Categorical(["a", "b"]))
|
||||
s2 = Series(Categorical(["a", "b"], categories=list("abc")))
|
||||
|
||||
if check_categorical:
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(s1, s2, check_categorical=check_categorical)
|
||||
else:
|
||||
_assert_series_equal_both(s1, s2, check_categorical=check_categorical)
|
||||
|
||||
|
||||
def test_assert_series_equal_extension_dtype_mismatch():
|
||||
# https://github.com/pandas-dev/pandas/issues/32747
|
||||
left = Series(pd.array([1, 2, 3], dtype="Int64"))
|
||||
right = left.astype(int)
|
||||
|
||||
msg = """Attributes of Series are different
|
||||
|
||||
Attribute "dtype" are different
|
||||
\\[left\\]: Int64
|
||||
\\[right\\]: int[32|64]"""
|
||||
|
||||
tm.assert_series_equal(left, right, check_dtype=False)
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(left, right, check_dtype=True)
|
||||
|
||||
|
||||
def test_assert_series_equal_interval_dtype_mismatch():
|
||||
# https://github.com/pandas-dev/pandas/issues/32747
|
||||
left = Series([pd.Interval(0, 1)], dtype="interval")
|
||||
right = left.astype(object)
|
||||
|
||||
msg = """Attributes of Series are different
|
||||
|
||||
Attribute "dtype" are different
|
||||
\\[left\\]: interval\\[int64, right\\]
|
||||
\\[right\\]: object"""
|
||||
|
||||
tm.assert_series_equal(left, right, check_dtype=False)
|
||||
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(left, right, check_dtype=True)
|
||||
|
||||
|
||||
def test_series_equal_series_type():
|
||||
class MySeries(Series):
|
||||
pass
|
||||
|
||||
s1 = Series([1, 2])
|
||||
s2 = Series([1, 2])
|
||||
s3 = MySeries([1, 2])
|
||||
|
||||
tm.assert_series_equal(s1, s2, check_series_type=False)
|
||||
tm.assert_series_equal(s1, s2, check_series_type=True)
|
||||
|
||||
tm.assert_series_equal(s1, s3, check_series_type=False)
|
||||
tm.assert_series_equal(s3, s1, check_series_type=False)
|
||||
|
||||
with pytest.raises(AssertionError, match="Series classes are different"):
|
||||
tm.assert_series_equal(s1, s3, check_series_type=True)
|
||||
|
||||
with pytest.raises(AssertionError, match="Series classes are different"):
|
||||
tm.assert_series_equal(s3, s1, check_series_type=True)
|
||||
|
||||
|
||||
def test_series_equal_exact_for_nonnumeric():
|
||||
# https://github.com/pandas-dev/pandas/issues/35446
|
||||
s1 = Series(["a", "b"])
|
||||
s2 = Series(["a", "b"])
|
||||
s3 = Series(["b", "a"])
|
||||
|
||||
tm.assert_series_equal(s1, s2, check_exact=True)
|
||||
tm.assert_series_equal(s2, s1, check_exact=True)
|
||||
|
||||
msg = """Series are different
|
||||
|
||||
Series values are different \\(100\\.0 %\\)
|
||||
\\[index\\]: \\[0, 1\\]
|
||||
\\[left\\]: \\[a, b\\]
|
||||
\\[right\\]: \\[b, a\\]"""
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(s1, s3, check_exact=True)
|
||||
|
||||
msg = """Series are different
|
||||
|
||||
Series values are different \\(100\\.0 %\\)
|
||||
\\[index\\]: \\[0, 1\\]
|
||||
\\[left\\]: \\[b, a\\]
|
||||
\\[right\\]: \\[a, b\\]"""
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
tm.assert_series_equal(s3, s1, check_exact=True)
|
||||
|
||||
|
||||
def test_assert_series_equal_ignore_extension_dtype_mismatch():
|
||||
# https://github.com/pandas-dev/pandas/issues/35715
|
||||
left = Series([1, 2, 3], dtype="Int64")
|
||||
right = Series([1, 2, 3], dtype="Int32")
|
||||
tm.assert_series_equal(left, right, check_dtype=False)
|
||||
|
||||
|
||||
def test_assert_series_equal_ignore_extension_dtype_mismatch_cross_class():
|
||||
# https://github.com/pandas-dev/pandas/issues/35715
|
||||
left = Series([1, 2, 3], dtype="Int64")
|
||||
right = Series([1, 2, 3], dtype="int64")
|
||||
tm.assert_series_equal(left, right, check_dtype=False)
|
||||
|
||||
|
||||
def test_allows_duplicate_labels():
|
||||
left = Series([1])
|
||||
right = Series([1]).set_flags(allows_duplicate_labels=False)
|
||||
tm.assert_series_equal(left, left)
|
||||
tm.assert_series_equal(right, right)
|
||||
tm.assert_series_equal(left, right, check_flags=False)
|
||||
tm.assert_series_equal(right, left, check_flags=False)
|
||||
|
||||
with pytest.raises(AssertionError, match="<Flags"):
|
||||
tm.assert_series_equal(left, right)
|
||||
|
||||
with pytest.raises(AssertionError, match="<Flags"):
|
||||
tm.assert_series_equal(left, right)
|
||||
|
||||
|
||||
def test_assert_series_equal_identical_na(nulls_fixture):
|
||||
ser = Series([nulls_fixture])
|
||||
|
||||
tm.assert_series_equal(ser, ser.copy())
|
||||
|
||||
# while we're here do Index too
|
||||
idx = pd.Index(ser)
|
||||
tm.assert_index_equal(idx, idx.copy(deep=True))
|
||||
|
||||
|
||||
def test_identical_nested_series_is_equal():
|
||||
# GH#22400
|
||||
x = Series(
|
||||
[
|
||||
0,
|
||||
0.0131142231938,
|
||||
1.77774652865e-05,
|
||||
np.array([0.4722720840328748, 0.4216929783681722]),
|
||||
]
|
||||
)
|
||||
y = Series(
|
||||
[
|
||||
0,
|
||||
0.0131142231938,
|
||||
1.77774652865e-05,
|
||||
np.array([0.4722720840328748, 0.4216929783681722]),
|
||||
]
|
||||
)
|
||||
# These two arrays should be equal, nesting could cause issue
|
||||
|
||||
tm.assert_series_equal(x, x)
|
||||
tm.assert_series_equal(x, x, check_exact=True)
|
||||
tm.assert_series_equal(x, y)
|
||||
tm.assert_series_equal(x, y, check_exact=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dtype", ["datetime64", "timedelta64"])
|
||||
def test_check_dtype_false_different_reso(dtype):
|
||||
# GH 52449
|
||||
ser_s = Series([1000213, 2131232, 21312331]).astype(f"{dtype}[s]")
|
||||
ser_ms = ser_s.astype(f"{dtype}[ms]")
|
||||
with pytest.raises(AssertionError, match="Attributes of Series are different"):
|
||||
tm.assert_series_equal(ser_s, ser_ms)
|
||||
tm.assert_series_equal(ser_ms, ser_s, check_dtype=False)
|
||||
|
||||
ser_ms -= Series([1, 1, 1]).astype(f"{dtype}[ms]")
|
||||
|
||||
with pytest.raises(AssertionError, match="Series are different"):
|
||||
tm.assert_series_equal(ser_s, ser_ms)
|
||||
|
||||
with pytest.raises(AssertionError, match="Series are different"):
|
||||
tm.assert_series_equal(ser_s, ser_ms, check_dtype=False)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dtype", ["Int64", "int64"])
|
||||
def test_large_unequal_ints(dtype):
|
||||
# https://github.com/pandas-dev/pandas/issues/55882
|
||||
left = Series([1577840521123000], dtype=dtype)
|
||||
right = Series([1577840521123543], dtype=dtype)
|
||||
with pytest.raises(AssertionError, match="Series are different"):
|
||||
tm.assert_series_equal(left, right)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dtype", [None, object])
|
||||
@pytest.mark.parametrize("check_exact", [True, False])
|
||||
@pytest.mark.parametrize("val", [3, 3.5])
|
||||
def test_ea_and_numpy_no_dtype_check(val, check_exact, dtype):
|
||||
# GH#56651
|
||||
left = Series([1, 2, val], dtype=dtype)
|
||||
right = Series(pd.array([1, 2, val]))
|
||||
tm.assert_series_equal(left, right, check_dtype=False, check_exact=check_exact)
|
||||
|
||||
|
||||
def test_assert_series_equal_int_tol():
|
||||
# GH#56646
|
||||
left = Series([81, 18, 121, 38, 74, 72, 81, 81, 146, 81, 81, 170, 74, 74])
|
||||
right = Series([72, 9, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72])
|
||||
tm.assert_series_equal(left, right, rtol=1.5)
|
||||
|
||||
tm.assert_frame_equal(left.to_frame(), right.to_frame(), rtol=1.5)
|
||||
tm.assert_extension_array_equal(
|
||||
left.astype("Int64").values, right.astype("Int64").values, rtol=1.5
|
||||
)
|
||||
|
||||
|
||||
def test_assert_series_equal_index_exact_default():
|
||||
# GH#57067
|
||||
ser1 = Series(np.zeros(6, dtype=int), [0, 0.2, 0.4, 0.6, 0.8, 1])
|
||||
ser2 = Series(np.zeros(6, dtype=int), np.linspace(0, 1, 6))
|
||||
tm.assert_series_equal(ser1, ser2)
|
||||
tm.assert_frame_equal(ser1.to_frame(), ser2.to_frame())
|
@ -0,0 +1,63 @@
|
||||
from textwrap import dedent
|
||||
|
||||
import pytest
|
||||
|
||||
from pandas.util._decorators import deprecate
|
||||
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def new_func():
|
||||
"""
|
||||
This is the summary. The deprecate directive goes next.
|
||||
|
||||
This is the extended summary. The deprecate directive goes before this.
|
||||
"""
|
||||
return "new_func called"
|
||||
|
||||
|
||||
def new_func_no_docstring():
|
||||
return "new_func_no_docstring called"
|
||||
|
||||
|
||||
def new_func_wrong_docstring():
|
||||
"""Summary should be in the next line."""
|
||||
return "new_func_wrong_docstring called"
|
||||
|
||||
|
||||
def new_func_with_deprecation():
|
||||
"""
|
||||
This is the summary. The deprecate directive goes next.
|
||||
|
||||
.. deprecated:: 1.0
|
||||
Use new_func instead.
|
||||
|
||||
This is the extended summary. The deprecate directive goes before this.
|
||||
"""
|
||||
|
||||
|
||||
def test_deprecate_ok():
|
||||
depr_func = deprecate("depr_func", new_func, "1.0", msg="Use new_func instead.")
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
result = depr_func()
|
||||
|
||||
assert result == "new_func called"
|
||||
assert depr_func.__doc__ == dedent(new_func_with_deprecation.__doc__)
|
||||
|
||||
|
||||
def test_deprecate_no_docstring():
|
||||
depr_func = deprecate(
|
||||
"depr_func", new_func_no_docstring, "1.0", msg="Use new_func instead."
|
||||
)
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
result = depr_func()
|
||||
assert result == "new_func_no_docstring called"
|
||||
|
||||
|
||||
def test_deprecate_wrong_docstring():
|
||||
msg = "deprecate needs a correctly formatted docstring"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
deprecate(
|
||||
"depr_func", new_func_wrong_docstring, "1.0", msg="Use new_func instead."
|
||||
)
|
@ -0,0 +1,90 @@
|
||||
import pytest
|
||||
|
||||
from pandas.util._decorators import deprecate_kwarg
|
||||
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
@deprecate_kwarg("old", "new")
|
||||
def _f1(new=False):
|
||||
return new
|
||||
|
||||
|
||||
_f2_mappings = {"yes": True, "no": False}
|
||||
|
||||
|
||||
@deprecate_kwarg("old", "new", _f2_mappings)
|
||||
def _f2(new=False):
|
||||
return new
|
||||
|
||||
|
||||
def _f3_mapping(x):
|
||||
return x + 1
|
||||
|
||||
|
||||
@deprecate_kwarg("old", "new", _f3_mapping)
|
||||
def _f3(new=0):
|
||||
return new
|
||||
|
||||
|
||||
@pytest.mark.parametrize("key,klass", [("old", FutureWarning), ("new", None)])
|
||||
def test_deprecate_kwarg(key, klass):
|
||||
x = 78
|
||||
|
||||
with tm.assert_produces_warning(klass):
|
||||
assert _f1(**{key: x}) == x
|
||||
|
||||
|
||||
@pytest.mark.parametrize("key", list(_f2_mappings.keys()))
|
||||
def test_dict_deprecate_kwarg(key):
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
assert _f2(old=key) == _f2_mappings[key]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("key", ["bogus", 12345, -1.23])
|
||||
def test_missing_deprecate_kwarg(key):
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
assert _f2(old=key) == key
|
||||
|
||||
|
||||
@pytest.mark.parametrize("x", [1, -1.4, 0])
|
||||
def test_callable_deprecate_kwarg(x):
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
assert _f3(old=x) == _f3_mapping(x)
|
||||
|
||||
|
||||
def test_callable_deprecate_kwarg_fail():
|
||||
msg = "((can only|cannot) concatenate)|(must be str)|(Can't convert)"
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
_f3(old="hello")
|
||||
|
||||
|
||||
def test_bad_deprecate_kwarg():
|
||||
msg = "mapping from old to new argument values must be dict or callable!"
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
|
||||
@deprecate_kwarg("old", "new", 0)
|
||||
def f4(new=None):
|
||||
return new
|
||||
|
||||
|
||||
@deprecate_kwarg("old", None)
|
||||
def _f4(old=True, unchanged=True):
|
||||
return old, unchanged
|
||||
|
||||
|
||||
@pytest.mark.parametrize("key", ["old", "unchanged"])
|
||||
def test_deprecate_keyword(key):
|
||||
x = 9
|
||||
|
||||
if key == "old":
|
||||
klass = FutureWarning
|
||||
expected = (x, True)
|
||||
else:
|
||||
klass = None
|
||||
expected = (True, x)
|
||||
|
||||
with tm.assert_produces_warning(klass):
|
||||
assert _f4(**{key: x}) == expected
|
@ -0,0 +1,141 @@
|
||||
"""
|
||||
Tests for the `deprecate_nonkeyword_arguments` decorator
|
||||
"""
|
||||
|
||||
import inspect
|
||||
|
||||
from pandas.util._decorators import deprecate_nonkeyword_arguments
|
||||
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
@deprecate_nonkeyword_arguments(
|
||||
version="1.1", allowed_args=["a", "b"], name="f_add_inputs"
|
||||
)
|
||||
def f(a, b=0, c=0, d=0):
|
||||
return a + b + c + d
|
||||
|
||||
|
||||
def test_f_signature():
|
||||
assert str(inspect.signature(f)) == "(a, b=0, *, c=0, d=0)"
|
||||
|
||||
|
||||
def test_one_argument():
|
||||
with tm.assert_produces_warning(None):
|
||||
assert f(19) == 19
|
||||
|
||||
|
||||
def test_one_and_one_arguments():
|
||||
with tm.assert_produces_warning(None):
|
||||
assert f(19, d=6) == 25
|
||||
|
||||
|
||||
def test_two_arguments():
|
||||
with tm.assert_produces_warning(None):
|
||||
assert f(1, 5) == 6
|
||||
|
||||
|
||||
def test_two_and_two_arguments():
|
||||
with tm.assert_produces_warning(None):
|
||||
assert f(1, 3, c=3, d=5) == 12
|
||||
|
||||
|
||||
def test_three_arguments():
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
assert f(6, 3, 3) == 12
|
||||
|
||||
|
||||
def test_four_arguments():
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
assert f(1, 2, 3, 4) == 10
|
||||
|
||||
|
||||
def test_three_arguments_with_name_in_warning():
|
||||
msg = (
|
||||
"Starting with pandas version 1.1 all arguments of f_add_inputs "
|
||||
"except for the arguments 'a' and 'b' will be keyword-only."
|
||||
)
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
assert f(6, 3, 3) == 12
|
||||
|
||||
|
||||
@deprecate_nonkeyword_arguments(version="1.1")
|
||||
def g(a, b=0, c=0, d=0):
|
||||
with tm.assert_produces_warning(None):
|
||||
return a + b + c + d
|
||||
|
||||
|
||||
def test_g_signature():
|
||||
assert str(inspect.signature(g)) == "(a, *, b=0, c=0, d=0)"
|
||||
|
||||
|
||||
def test_one_and_three_arguments_default_allowed_args():
|
||||
with tm.assert_produces_warning(None):
|
||||
assert g(1, b=3, c=3, d=5) == 12
|
||||
|
||||
|
||||
def test_three_arguments_default_allowed_args():
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
assert g(6, 3, 3) == 12
|
||||
|
||||
|
||||
def test_three_positional_argument_with_warning_message_analysis():
|
||||
msg = (
|
||||
"Starting with pandas version 1.1 all arguments of g "
|
||||
"except for the argument 'a' will be keyword-only."
|
||||
)
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
assert g(6, 3, 3) == 12
|
||||
|
||||
|
||||
@deprecate_nonkeyword_arguments(version="1.1")
|
||||
def h(a=0, b=0, c=0, d=0):
|
||||
return a + b + c + d
|
||||
|
||||
|
||||
def test_h_signature():
|
||||
assert str(inspect.signature(h)) == "(*, a=0, b=0, c=0, d=0)"
|
||||
|
||||
|
||||
def test_all_keyword_arguments():
|
||||
with tm.assert_produces_warning(None):
|
||||
assert h(a=1, b=2) == 3
|
||||
|
||||
|
||||
def test_one_positional_argument():
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
assert h(23) == 23
|
||||
|
||||
|
||||
def test_one_positional_argument_with_warning_message_analysis():
|
||||
msg = "Starting with pandas version 1.1 all arguments of h will be keyword-only."
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
assert h(19) == 19
|
||||
|
||||
|
||||
@deprecate_nonkeyword_arguments(version="1.1")
|
||||
def i(a=0, /, b=0, *, c=0, d=0):
|
||||
return a + b + c + d
|
||||
|
||||
|
||||
def test_i_signature():
|
||||
assert str(inspect.signature(i)) == "(*, a=0, b=0, c=0, d=0)"
|
||||
|
||||
|
||||
class Foo:
|
||||
@deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "bar"])
|
||||
def baz(self, bar=None, foobar=None): # pylint: disable=disallowed-name
|
||||
...
|
||||
|
||||
|
||||
def test_foo_signature():
|
||||
assert str(inspect.signature(Foo.baz)) == "(self, bar=None, *, foobar=None)"
|
||||
|
||||
|
||||
def test_class():
|
||||
msg = (
|
||||
r"In a future version of pandas all arguments of Foo\.baz "
|
||||
r"except for the argument \'bar\' will be keyword-only"
|
||||
)
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
Foo().baz("qux", "quox")
|
@ -0,0 +1,90 @@
|
||||
from textwrap import dedent
|
||||
|
||||
from pandas.util._decorators import doc
|
||||
|
||||
|
||||
@doc(method="cumsum", operation="sum")
|
||||
def cumsum(whatever):
|
||||
"""
|
||||
This is the {method} method.
|
||||
|
||||
It computes the cumulative {operation}.
|
||||
"""
|
||||
|
||||
|
||||
@doc(
|
||||
cumsum,
|
||||
dedent(
|
||||
"""
|
||||
Examples
|
||||
--------
|
||||
|
||||
>>> cumavg([1, 2, 3])
|
||||
2
|
||||
"""
|
||||
),
|
||||
method="cumavg",
|
||||
operation="average",
|
||||
)
|
||||
def cumavg(whatever):
|
||||
pass
|
||||
|
||||
|
||||
@doc(cumsum, method="cummax", operation="maximum")
|
||||
def cummax(whatever):
|
||||
pass
|
||||
|
||||
|
||||
@doc(cummax, method="cummin", operation="minimum")
|
||||
def cummin(whatever):
|
||||
pass
|
||||
|
||||
|
||||
def test_docstring_formatting():
|
||||
docstr = dedent(
|
||||
"""
|
||||
This is the cumsum method.
|
||||
|
||||
It computes the cumulative sum.
|
||||
"""
|
||||
)
|
||||
assert cumsum.__doc__ == docstr
|
||||
|
||||
|
||||
def test_docstring_appending():
|
||||
docstr = dedent(
|
||||
"""
|
||||
This is the cumavg method.
|
||||
|
||||
It computes the cumulative average.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
>>> cumavg([1, 2, 3])
|
||||
2
|
||||
"""
|
||||
)
|
||||
assert cumavg.__doc__ == docstr
|
||||
|
||||
|
||||
def test_doc_template_from_func():
|
||||
docstr = dedent(
|
||||
"""
|
||||
This is the cummax method.
|
||||
|
||||
It computes the cumulative maximum.
|
||||
"""
|
||||
)
|
||||
assert cummax.__doc__ == docstr
|
||||
|
||||
|
||||
def test_inherit_doc_template():
|
||||
docstr = dedent(
|
||||
"""
|
||||
This is the cummin method.
|
||||
|
||||
It computes the cumulative minimum.
|
||||
"""
|
||||
)
|
||||
assert cummin.__doc__ == docstr
|
@ -0,0 +1,417 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import (
|
||||
DataFrame,
|
||||
Index,
|
||||
MultiIndex,
|
||||
Series,
|
||||
period_range,
|
||||
timedelta_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
from pandas.core.util.hashing import hash_tuples
|
||||
from pandas.util import (
|
||||
hash_array,
|
||||
hash_pandas_object,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
params=[
|
||||
Series([1, 2, 3] * 3, dtype="int32"),
|
||||
Series([None, 2.5, 3.5] * 3, dtype="float32"),
|
||||
Series(["a", "b", "c"] * 3, dtype="category"),
|
||||
Series(["d", "e", "f"] * 3),
|
||||
Series([True, False, True] * 3),
|
||||
Series(pd.date_range("20130101", periods=9)),
|
||||
Series(pd.date_range("20130101", periods=9, tz="US/Eastern")),
|
||||
Series(timedelta_range("2000", periods=9)),
|
||||
]
|
||||
)
|
||||
def series(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(params=[True, False])
|
||||
def index(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_consistency():
|
||||
# Check that our hash doesn't change because of a mistake
|
||||
# in the actual code; this is the ground truth.
|
||||
result = hash_pandas_object(Index(["foo", "bar", "baz"]))
|
||||
expected = Series(
|
||||
np.array(
|
||||
[3600424527151052760, 1374399572096150070, 477881037637427054],
|
||||
dtype="uint64",
|
||||
),
|
||||
index=["foo", "bar", "baz"],
|
||||
)
|
||||
tm.assert_series_equal(result, expected)
|
||||
|
||||
|
||||
def test_hash_array(series):
|
||||
arr = series.values
|
||||
tm.assert_numpy_array_equal(hash_array(arr), hash_array(arr))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dtype", ["U", object])
|
||||
def test_hash_array_mixed(dtype):
|
||||
result1 = hash_array(np.array(["3", "4", "All"]))
|
||||
result2 = hash_array(np.array([3, 4, "All"], dtype=dtype))
|
||||
|
||||
tm.assert_numpy_array_equal(result1, result2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("val", [5, "foo", pd.Timestamp("20130101")])
|
||||
def test_hash_array_errors(val):
|
||||
msg = "must pass a ndarray-like"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
hash_array(val)
|
||||
|
||||
|
||||
def test_hash_array_index_exception():
|
||||
# GH42003 TypeError instead of AttributeError
|
||||
obj = pd.DatetimeIndex(["2018-10-28 01:20:00"], tz="Europe/Berlin")
|
||||
|
||||
msg = "Use hash_pandas_object instead"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
hash_array(obj)
|
||||
|
||||
|
||||
def test_hash_tuples():
|
||||
tuples = [(1, "one"), (1, "two"), (2, "one")]
|
||||
result = hash_tuples(tuples)
|
||||
|
||||
expected = hash_pandas_object(MultiIndex.from_tuples(tuples)).values
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
# We only need to support MultiIndex and list-of-tuples
|
||||
msg = "|".join(["object is not iterable", "zip argument #1 must support iteration"])
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
hash_tuples(tuples[0])
|
||||
|
||||
|
||||
@pytest.mark.parametrize("val", [5, "foo", pd.Timestamp("20130101")])
|
||||
def test_hash_tuples_err(val):
|
||||
msg = "must be convertible to a list-of-tuples"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
hash_tuples(val)
|
||||
|
||||
|
||||
def test_multiindex_unique():
|
||||
mi = MultiIndex.from_tuples([(118, 472), (236, 118), (51, 204), (102, 51)])
|
||||
assert mi.is_unique is True
|
||||
|
||||
result = hash_pandas_object(mi)
|
||||
assert result.is_unique is True
|
||||
|
||||
|
||||
def test_multiindex_objects():
|
||||
mi = MultiIndex(
|
||||
levels=[["b", "d", "a"], [1, 2, 3]],
|
||||
codes=[[0, 1, 0, 2], [2, 0, 0, 1]],
|
||||
names=["col1", "col2"],
|
||||
)
|
||||
recons = mi._sort_levels_monotonic()
|
||||
|
||||
# These are equal.
|
||||
assert mi.equals(recons)
|
||||
assert Index(mi.values).equals(Index(recons.values))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"obj",
|
||||
[
|
||||
Series([1, 2, 3]),
|
||||
Series([1.0, 1.5, 3.2]),
|
||||
Series([1.0, 1.5, np.nan]),
|
||||
Series([1.0, 1.5, 3.2], index=[1.5, 1.1, 3.3]),
|
||||
Series(["a", "b", "c"]),
|
||||
Series(["a", np.nan, "c"]),
|
||||
Series(["a", None, "c"]),
|
||||
Series([True, False, True]),
|
||||
Series(dtype=object),
|
||||
DataFrame({"x": ["a", "b", "c"], "y": [1, 2, 3]}),
|
||||
DataFrame(),
|
||||
DataFrame(np.full((10, 4), np.nan)),
|
||||
DataFrame(
|
||||
{
|
||||
"A": [0.0, 1.0, 2.0, 3.0, 4.0],
|
||||
"B": [0.0, 1.0, 0.0, 1.0, 0.0],
|
||||
"C": Index(["foo1", "foo2", "foo3", "foo4", "foo5"], dtype=object),
|
||||
"D": pd.date_range("20130101", periods=5),
|
||||
}
|
||||
),
|
||||
DataFrame(range(5), index=pd.date_range("2020-01-01", periods=5)),
|
||||
Series(range(5), index=pd.date_range("2020-01-01", periods=5)),
|
||||
Series(period_range("2020-01-01", periods=10, freq="D")),
|
||||
Series(pd.date_range("20130101", periods=3, tz="US/Eastern")),
|
||||
],
|
||||
)
|
||||
def test_hash_pandas_object(obj, index):
|
||||
a = hash_pandas_object(obj, index=index)
|
||||
b = hash_pandas_object(obj, index=index)
|
||||
tm.assert_series_equal(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"obj",
|
||||
[
|
||||
Series([1, 2, 3]),
|
||||
Series([1.0, 1.5, 3.2]),
|
||||
Series([1.0, 1.5, np.nan]),
|
||||
Series([1.0, 1.5, 3.2], index=[1.5, 1.1, 3.3]),
|
||||
Series(["a", "b", "c"]),
|
||||
Series(["a", np.nan, "c"]),
|
||||
Series(["a", None, "c"]),
|
||||
Series([True, False, True]),
|
||||
DataFrame({"x": ["a", "b", "c"], "y": [1, 2, 3]}),
|
||||
DataFrame(np.full((10, 4), np.nan)),
|
||||
DataFrame(
|
||||
{
|
||||
"A": [0.0, 1.0, 2.0, 3.0, 4.0],
|
||||
"B": [0.0, 1.0, 0.0, 1.0, 0.0],
|
||||
"C": Index(["foo1", "foo2", "foo3", "foo4", "foo5"], dtype=object),
|
||||
"D": pd.date_range("20130101", periods=5),
|
||||
}
|
||||
),
|
||||
DataFrame(range(5), index=pd.date_range("2020-01-01", periods=5)),
|
||||
Series(range(5), index=pd.date_range("2020-01-01", periods=5)),
|
||||
Series(period_range("2020-01-01", periods=10, freq="D")),
|
||||
Series(pd.date_range("20130101", periods=3, tz="US/Eastern")),
|
||||
],
|
||||
)
|
||||
def test_hash_pandas_object_diff_index_non_empty(obj):
|
||||
a = hash_pandas_object(obj, index=True)
|
||||
b = hash_pandas_object(obj, index=False)
|
||||
assert not (a == b).all()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"obj",
|
||||
[
|
||||
Index([1, 2, 3]),
|
||||
Index([True, False, True]),
|
||||
timedelta_range("1 day", periods=2),
|
||||
period_range("2020-01-01", freq="D", periods=2),
|
||||
MultiIndex.from_product(
|
||||
[range(5), ["foo", "bar", "baz"], pd.date_range("20130101", periods=2)]
|
||||
),
|
||||
MultiIndex.from_product([pd.CategoricalIndex(list("aabc")), range(3)]),
|
||||
],
|
||||
)
|
||||
def test_hash_pandas_index(obj, index):
|
||||
a = hash_pandas_object(obj, index=index)
|
||||
b = hash_pandas_object(obj, index=index)
|
||||
tm.assert_series_equal(a, b)
|
||||
|
||||
|
||||
def test_hash_pandas_series(series, index):
|
||||
a = hash_pandas_object(series, index=index)
|
||||
b = hash_pandas_object(series, index=index)
|
||||
tm.assert_series_equal(a, b)
|
||||
|
||||
|
||||
def test_hash_pandas_series_diff_index(series):
|
||||
a = hash_pandas_object(series, index=True)
|
||||
b = hash_pandas_object(series, index=False)
|
||||
assert not (a == b).all()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"obj", [Series([], dtype="float64"), Series([], dtype="object"), Index([])]
|
||||
)
|
||||
def test_hash_pandas_empty_object(obj, index):
|
||||
# These are by-definition the same with
|
||||
# or without the index as the data is empty.
|
||||
a = hash_pandas_object(obj, index=index)
|
||||
b = hash_pandas_object(obj, index=index)
|
||||
tm.assert_series_equal(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"s1",
|
||||
[
|
||||
Series(["a", "b", "c", "d"]),
|
||||
Series([1000, 2000, 3000, 4000]),
|
||||
Series(pd.date_range(0, periods=4)),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("categorize", [True, False])
|
||||
def test_categorical_consistency(s1, categorize):
|
||||
# see gh-15143
|
||||
#
|
||||
# Check that categoricals hash consistent with their values,
|
||||
# not codes. This should work for categoricals of any dtype.
|
||||
s2 = s1.astype("category").cat.set_categories(s1)
|
||||
s3 = s2.cat.set_categories(list(reversed(s1)))
|
||||
|
||||
# These should all hash identically.
|
||||
h1 = hash_pandas_object(s1, categorize=categorize)
|
||||
h2 = hash_pandas_object(s2, categorize=categorize)
|
||||
h3 = hash_pandas_object(s3, categorize=categorize)
|
||||
|
||||
tm.assert_series_equal(h1, h2)
|
||||
tm.assert_series_equal(h1, h3)
|
||||
|
||||
|
||||
def test_categorical_with_nan_consistency():
|
||||
c = pd.Categorical.from_codes(
|
||||
[-1, 0, 1, 2, 3, 4], categories=pd.date_range("2012-01-01", periods=5, name="B")
|
||||
)
|
||||
expected = hash_array(c, categorize=False)
|
||||
|
||||
c = pd.Categorical.from_codes([-1, 0], categories=[pd.Timestamp("2012-01-01")])
|
||||
result = hash_array(c, categorize=False)
|
||||
|
||||
assert result[0] in expected
|
||||
assert result[1] in expected
|
||||
|
||||
|
||||
def test_pandas_errors():
|
||||
msg = "Unexpected type for hashing"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
hash_pandas_object(pd.Timestamp("20130101"))
|
||||
|
||||
|
||||
def test_hash_keys():
|
||||
# Using different hash keys, should have
|
||||
# different hashes for the same data.
|
||||
#
|
||||
# This only matters for object dtypes.
|
||||
obj = Series(list("abc"))
|
||||
|
||||
a = hash_pandas_object(obj, hash_key="9876543210123456")
|
||||
b = hash_pandas_object(obj, hash_key="9876543210123465")
|
||||
|
||||
assert (a != b).all()
|
||||
|
||||
|
||||
def test_df_hash_keys():
|
||||
# DataFrame version of the test_hash_keys.
|
||||
# https://github.com/pandas-dev/pandas/issues/41404
|
||||
obj = DataFrame({"x": np.arange(3), "y": list("abc")})
|
||||
|
||||
a = hash_pandas_object(obj, hash_key="9876543210123456")
|
||||
b = hash_pandas_object(obj, hash_key="9876543210123465")
|
||||
|
||||
assert (a != b).all()
|
||||
|
||||
|
||||
def test_df_encoding():
|
||||
# Check that DataFrame recognizes optional encoding.
|
||||
# https://github.com/pandas-dev/pandas/issues/41404
|
||||
# https://github.com/pandas-dev/pandas/pull/42049
|
||||
obj = DataFrame({"x": np.arange(3), "y": list("a+c")})
|
||||
|
||||
a = hash_pandas_object(obj, encoding="utf8")
|
||||
b = hash_pandas_object(obj, encoding="utf7")
|
||||
|
||||
# Note that the "+" is encoded as "+-" in utf-7.
|
||||
assert a[0] == b[0]
|
||||
assert a[1] != b[1]
|
||||
assert a[2] == b[2]
|
||||
|
||||
|
||||
def test_invalid_key():
|
||||
# This only matters for object dtypes.
|
||||
msg = "key should be a 16-byte string encoded"
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
hash_pandas_object(Series(list("abc")), hash_key="foo")
|
||||
|
||||
|
||||
def test_already_encoded(index):
|
||||
# If already encoded, then ok.
|
||||
obj = Series(list("abc")).str.encode("utf8")
|
||||
a = hash_pandas_object(obj, index=index)
|
||||
b = hash_pandas_object(obj, index=index)
|
||||
tm.assert_series_equal(a, b)
|
||||
|
||||
|
||||
def test_alternate_encoding(index):
|
||||
obj = Series(list("abc"))
|
||||
a = hash_pandas_object(obj, index=index)
|
||||
b = hash_pandas_object(obj, index=index)
|
||||
tm.assert_series_equal(a, b)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("l_exp", range(8))
|
||||
@pytest.mark.parametrize("l_add", [0, 1])
|
||||
def test_same_len_hash_collisions(l_exp, l_add):
|
||||
length = 2 ** (l_exp + 8) + l_add
|
||||
idx = np.array([str(i) for i in range(length)], dtype=object)
|
||||
|
||||
result = hash_array(idx, "utf8")
|
||||
assert not result[0] == result[1]
|
||||
|
||||
|
||||
def test_hash_collisions():
|
||||
# Hash collisions are bad.
|
||||
#
|
||||
# https://github.com/pandas-dev/pandas/issues/14711#issuecomment-264885726
|
||||
hashes = [
|
||||
"Ingrid-9Z9fKIZmkO7i7Cn51Li34pJm44fgX6DYGBNj3VPlOH50m7HnBlPxfIwFMrcNJNMP6PSgLmwWnInciMWrCSAlLEvt7JkJl4IxiMrVbXSa8ZQoVaq5xoQPjltuJEfwdNlO6jo8qRRHvD8sBEBMQASrRa6TsdaPTPCBo3nwIBpE7YzzmyH0vMBhjQZLx1aCT7faSEx7PgFxQhHdKFWROcysamgy9iVj8DO2Fmwg1NNl93rIAqC3mdqfrCxrzfvIY8aJdzin2cHVzy3QUJxZgHvtUtOLxoqnUHsYbNTeq0xcLXpTZEZCxD4PGubIuCNf32c33M7HFsnjWSEjE2yVdWKhmSVodyF8hFYVmhYnMCztQnJrt3O8ZvVRXd5IKwlLexiSp4h888w7SzAIcKgc3g5XQJf6MlSMftDXm9lIsE1mJNiJEv6uY6pgvC3fUPhatlR5JPpVAHNSbSEE73MBzJrhCAbOLXQumyOXigZuPoME7QgJcBalliQol7YZ9",
|
||||
"Tim-b9MddTxOWW2AT1Py6vtVbZwGAmYCjbp89p8mxsiFoVX4FyDOF3wFiAkyQTUgwg9sVqVYOZo09Dh1AzhFHbgij52ylF0SEwgzjzHH8TGY8Lypart4p4onnDoDvVMBa0kdthVGKl6K0BDVGzyOXPXKpmnMF1H6rJzqHJ0HywfwS4XYpVwlAkoeNsiicHkJUFdUAhG229INzvIAiJuAHeJDUoyO4DCBqtoZ5TDend6TK7Y914yHlfH3g1WZu5LksKv68VQHJriWFYusW5e6ZZ6dKaMjTwEGuRgdT66iU5nqWTHRH8WSzpXoCFwGcTOwyuqPSe0fTe21DVtJn1FKj9F9nEnR9xOvJUO7E0piCIF4Ad9yAIDY4DBimpsTfKXCu1vdHpKYerzbndfuFe5AhfMduLYZJi5iAw8qKSwR5h86ttXV0Mc0QmXz8dsRvDgxjXSmupPxBggdlqUlC828hXiTPD7am0yETBV0F3bEtvPiNJfremszcV8NcqAoARMe",
|
||||
]
|
||||
|
||||
# These should be different.
|
||||
result1 = hash_array(np.asarray(hashes[0:1], dtype=object), "utf8")
|
||||
expected1 = np.array([14963968704024874985], dtype=np.uint64)
|
||||
tm.assert_numpy_array_equal(result1, expected1)
|
||||
|
||||
result2 = hash_array(np.asarray(hashes[1:2], dtype=object), "utf8")
|
||||
expected2 = np.array([16428432627716348016], dtype=np.uint64)
|
||||
tm.assert_numpy_array_equal(result2, expected2)
|
||||
|
||||
result = hash_array(np.asarray(hashes, dtype=object), "utf8")
|
||||
tm.assert_numpy_array_equal(result, np.concatenate([expected1, expected2], axis=0))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"data, result_data",
|
||||
[
|
||||
[[tuple("1"), tuple("2")], [10345501319357378243, 8331063931016360761]],
|
||||
[[(1,), (2,)], [9408946347443669104, 3278256261030523334]],
|
||||
],
|
||||
)
|
||||
def test_hash_with_tuple(data, result_data):
|
||||
# GH#28969 array containing a tuple raises on call to arr.astype(str)
|
||||
# apparently a numpy bug github.com/numpy/numpy/issues/9441
|
||||
|
||||
df = DataFrame({"data": data})
|
||||
result = hash_pandas_object(df)
|
||||
expected = Series(result_data, dtype=np.uint64)
|
||||
tm.assert_series_equal(result, expected)
|
||||
|
||||
|
||||
def test_hashable_tuple_args():
|
||||
# require that the elements of such tuples are themselves hashable
|
||||
|
||||
df3 = DataFrame(
|
||||
{
|
||||
"data": [
|
||||
(
|
||||
1,
|
||||
[],
|
||||
),
|
||||
(
|
||||
2,
|
||||
{},
|
||||
),
|
||||
]
|
||||
}
|
||||
)
|
||||
with pytest.raises(TypeError, match="unhashable type: 'list'"):
|
||||
hash_pandas_object(df3)
|
||||
|
||||
|
||||
def test_hash_object_none_key():
|
||||
# https://github.com/pandas-dev/pandas/issues/30887
|
||||
result = pd.util.hash_pandas_object(Series(["a", "b"]), hash_key=None)
|
||||
expected = Series([4578374827886788867, 17338122309987883691], dtype="uint64")
|
||||
tm.assert_series_equal(result, expected)
|
@ -0,0 +1,12 @@
|
||||
import pytest
|
||||
|
||||
import pandas.util._test_decorators as td
|
||||
|
||||
from pandas import option_context
|
||||
|
||||
|
||||
@td.skip_if_installed("numba")
|
||||
def test_numba_not_installed_option_context():
|
||||
with pytest.raises(ImportError, match="Missing optional"):
|
||||
with option_context("compute.use_numba", True):
|
||||
pass
|
@ -0,0 +1,39 @@
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
|
||||
from pandas.util._exceptions import rewrite_warning
|
||||
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"target_category, target_message, hit",
|
||||
[
|
||||
(FutureWarning, "Target message", True),
|
||||
(FutureWarning, "Target", True),
|
||||
(FutureWarning, "get mess", True),
|
||||
(FutureWarning, "Missed message", False),
|
||||
(DeprecationWarning, "Target message", False),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"new_category",
|
||||
[
|
||||
None,
|
||||
DeprecationWarning,
|
||||
],
|
||||
)
|
||||
def test_rewrite_warning(target_category, target_message, hit, new_category):
|
||||
new_message = "Rewritten message"
|
||||
if hit:
|
||||
expected_category = new_category if new_category else target_category
|
||||
expected_message = new_message
|
||||
else:
|
||||
expected_category = FutureWarning
|
||||
expected_message = "Target message"
|
||||
with tm.assert_produces_warning(expected_category, match=expected_message):
|
||||
with rewrite_warning(
|
||||
target_message, target_category, new_message, new_category
|
||||
):
|
||||
warnings.warn(message="Target message", category=FutureWarning)
|
@ -0,0 +1,30 @@
|
||||
import pandas.util._test_decorators as td
|
||||
|
||||
import pandas as pd
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def test_shares_memory_interval():
|
||||
obj = pd.interval_range(1, 5)
|
||||
|
||||
assert tm.shares_memory(obj, obj)
|
||||
assert tm.shares_memory(obj, obj._data)
|
||||
assert tm.shares_memory(obj, obj[::-1])
|
||||
assert tm.shares_memory(obj, obj[:2])
|
||||
|
||||
assert not tm.shares_memory(obj, obj._data.copy())
|
||||
|
||||
|
||||
@td.skip_if_no("pyarrow")
|
||||
def test_shares_memory_string():
|
||||
# GH#55823
|
||||
import pyarrow as pa
|
||||
|
||||
obj = pd.array(["a", "b"], dtype="string[pyarrow]")
|
||||
assert tm.shares_memory(obj, obj)
|
||||
|
||||
obj = pd.array(["a", "b"], dtype="string[pyarrow_numpy]")
|
||||
assert tm.shares_memory(obj, obj)
|
||||
|
||||
obj = pd.array(["a", "b"], dtype=pd.ArrowDtype(pa.string()))
|
||||
assert tm.shares_memory(obj, obj)
|
@ -0,0 +1,81 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
from pandas.util._print_versions import (
|
||||
_get_dependency_info,
|
||||
_get_sys_info,
|
||||
)
|
||||
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def test_show_versions(tmpdir):
|
||||
# GH39701
|
||||
as_json = os.path.join(tmpdir, "test_output.json")
|
||||
|
||||
pd.show_versions(as_json=as_json)
|
||||
|
||||
with open(as_json, encoding="utf-8") as fd:
|
||||
# check if file output is valid JSON, will raise an exception if not
|
||||
result = json.load(fd)
|
||||
|
||||
# Basic check that each version element is found in output
|
||||
expected = {
|
||||
"system": _get_sys_info(),
|
||||
"dependencies": _get_dependency_info(),
|
||||
}
|
||||
|
||||
assert result == expected
|
||||
|
||||
|
||||
def test_show_versions_console_json(capsys):
|
||||
# GH39701
|
||||
pd.show_versions(as_json=True)
|
||||
stdout = capsys.readouterr().out
|
||||
|
||||
# check valid json is printed to the console if as_json is True
|
||||
result = json.loads(stdout)
|
||||
|
||||
# Basic check that each version element is found in output
|
||||
expected = {
|
||||
"system": _get_sys_info(),
|
||||
"dependencies": _get_dependency_info(),
|
||||
}
|
||||
|
||||
assert result == expected
|
||||
|
||||
|
||||
def test_show_versions_console(capsys):
|
||||
# gh-32041
|
||||
# gh-32041
|
||||
pd.show_versions(as_json=False)
|
||||
result = capsys.readouterr().out
|
||||
|
||||
# check header
|
||||
assert "INSTALLED VERSIONS" in result
|
||||
|
||||
# check full commit hash
|
||||
assert re.search(r"commit\s*:\s[0-9a-f]{40}\n", result)
|
||||
|
||||
# check required dependency
|
||||
# 2020-12-09 npdev has "dirty" in the tag
|
||||
# 2022-05-25 npdev released with RC wo/ "dirty".
|
||||
# Just ensure we match [0-9]+\..* since npdev version is variable
|
||||
assert re.search(r"numpy\s*:\s[0-9]+\..*\n", result)
|
||||
|
||||
# check optional dependency
|
||||
assert re.search(r"pyarrow\s*:\s([0-9]+.*|None)\n", result)
|
||||
|
||||
|
||||
def test_json_output_match(capsys, tmpdir):
|
||||
# GH39701
|
||||
pd.show_versions(as_json=True)
|
||||
result_console = capsys.readouterr().out
|
||||
|
||||
out_path = os.path.join(tmpdir, "test_json.json")
|
||||
pd.show_versions(as_json=out_path)
|
||||
with open(out_path, encoding="utf-8") as out_fd:
|
||||
result_file = out_fd.read()
|
||||
|
||||
assert result_console == result_file
|
@ -0,0 +1,58 @@
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
array,
|
||||
compat,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def test_numpy_err_state_is_default():
|
||||
expected = {"over": "warn", "divide": "warn", "invalid": "warn", "under": "ignore"}
|
||||
import numpy as np
|
||||
|
||||
# The error state should be unchanged after that import.
|
||||
assert np.geterr() == expected
|
||||
|
||||
|
||||
def test_convert_rows_list_to_csv_str():
|
||||
rows_list = ["aaa", "bbb", "ccc"]
|
||||
ret = tm.convert_rows_list_to_csv_str(rows_list)
|
||||
|
||||
if compat.is_platform_windows():
|
||||
expected = "aaa\r\nbbb\r\nccc\r\n"
|
||||
else:
|
||||
expected = "aaa\nbbb\nccc\n"
|
||||
|
||||
assert ret == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("strict_data_files", [True, False])
|
||||
def test_datapath_missing(datapath):
|
||||
with pytest.raises(ValueError, match="Could not find file"):
|
||||
datapath("not_a_file")
|
||||
|
||||
|
||||
def test_datapath(datapath):
|
||||
args = ("io", "data", "csv", "iris.csv")
|
||||
|
||||
result = datapath(*args)
|
||||
expected = os.path.join(os.path.dirname(os.path.dirname(__file__)), *args)
|
||||
|
||||
assert result == expected
|
||||
|
||||
|
||||
def test_external_error_raised():
|
||||
with tm.external_error_raised(TypeError):
|
||||
raise TypeError("Should not check this error message, so it will pass")
|
||||
|
||||
|
||||
def test_is_sorted():
|
||||
arr = array([1, 2, 3], dtype="Int64")
|
||||
tm.assert_is_sorted(arr)
|
||||
|
||||
arr = array([4, 2, 3], dtype="Int64")
|
||||
with pytest.raises(AssertionError, match="ExtensionArray are different"):
|
||||
tm.assert_is_sorted(arr)
|
@ -0,0 +1,70 @@
|
||||
import pytest
|
||||
|
||||
from pandas.util._validators import validate_args
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def _fname():
|
||||
return "func"
|
||||
|
||||
|
||||
def test_bad_min_fname_arg_count(_fname):
|
||||
msg = "'max_fname_arg_count' must be non-negative"
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
validate_args(_fname, (None,), -1, "foo")
|
||||
|
||||
|
||||
def test_bad_arg_length_max_value_single(_fname):
|
||||
args = (None, None)
|
||||
compat_args = ("foo",)
|
||||
|
||||
min_fname_arg_count = 0
|
||||
max_length = len(compat_args) + min_fname_arg_count
|
||||
actual_length = len(args) + min_fname_arg_count
|
||||
msg = (
|
||||
rf"{_fname}\(\) takes at most {max_length} "
|
||||
rf"argument \({actual_length} given\)"
|
||||
)
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
validate_args(_fname, args, min_fname_arg_count, compat_args)
|
||||
|
||||
|
||||
def test_bad_arg_length_max_value_multiple(_fname):
|
||||
args = (None, None)
|
||||
compat_args = {"foo": None}
|
||||
|
||||
min_fname_arg_count = 2
|
||||
max_length = len(compat_args) + min_fname_arg_count
|
||||
actual_length = len(args) + min_fname_arg_count
|
||||
msg = (
|
||||
rf"{_fname}\(\) takes at most {max_length} "
|
||||
rf"arguments \({actual_length} given\)"
|
||||
)
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
validate_args(_fname, args, min_fname_arg_count, compat_args)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("i", range(1, 3))
|
||||
def test_not_all_defaults(i, _fname):
|
||||
bad_arg = "foo"
|
||||
msg = (
|
||||
f"the '{bad_arg}' parameter is not supported "
|
||||
rf"in the pandas implementation of {_fname}\(\)"
|
||||
)
|
||||
|
||||
compat_args = {"foo": 2, "bar": -1, "baz": 3}
|
||||
arg_vals = (1, -1, 3)
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
validate_args(_fname, arg_vals[:i], 2, compat_args)
|
||||
|
||||
|
||||
def test_validation(_fname):
|
||||
# No exceptions should be raised.
|
||||
validate_args(_fname, (None,), 2, {"out": None})
|
||||
|
||||
compat_args = {"axis": 1, "out": None}
|
||||
validate_args(_fname, (1, None), 2, compat_args)
|
@ -0,0 +1,84 @@
|
||||
import pytest
|
||||
|
||||
from pandas.util._validators import validate_args_and_kwargs
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def _fname():
|
||||
return "func"
|
||||
|
||||
|
||||
def test_invalid_total_length_max_length_one(_fname):
|
||||
compat_args = ("foo",)
|
||||
kwargs = {"foo": "FOO"}
|
||||
args = ("FoO", "BaZ")
|
||||
|
||||
min_fname_arg_count = 0
|
||||
max_length = len(compat_args) + min_fname_arg_count
|
||||
actual_length = len(kwargs) + len(args) + min_fname_arg_count
|
||||
|
||||
msg = (
|
||||
rf"{_fname}\(\) takes at most {max_length} "
|
||||
rf"argument \({actual_length} given\)"
|
||||
)
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
validate_args_and_kwargs(_fname, args, kwargs, min_fname_arg_count, compat_args)
|
||||
|
||||
|
||||
def test_invalid_total_length_max_length_multiple(_fname):
|
||||
compat_args = ("foo", "bar", "baz")
|
||||
kwargs = {"foo": "FOO", "bar": "BAR"}
|
||||
args = ("FoO", "BaZ")
|
||||
|
||||
min_fname_arg_count = 2
|
||||
max_length = len(compat_args) + min_fname_arg_count
|
||||
actual_length = len(kwargs) + len(args) + min_fname_arg_count
|
||||
|
||||
msg = (
|
||||
rf"{_fname}\(\) takes at most {max_length} "
|
||||
rf"arguments \({actual_length} given\)"
|
||||
)
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
validate_args_and_kwargs(_fname, args, kwargs, min_fname_arg_count, compat_args)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("args,kwargs", [((), {"foo": -5, "bar": 2}), ((-5, 2), {})])
|
||||
def test_missing_args_or_kwargs(args, kwargs, _fname):
|
||||
bad_arg = "bar"
|
||||
min_fname_arg_count = 2
|
||||
|
||||
compat_args = {"foo": -5, bad_arg: 1}
|
||||
|
||||
msg = (
|
||||
rf"the '{bad_arg}' parameter is not supported "
|
||||
rf"in the pandas implementation of {_fname}\(\)"
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
validate_args_and_kwargs(_fname, args, kwargs, min_fname_arg_count, compat_args)
|
||||
|
||||
|
||||
def test_duplicate_argument(_fname):
|
||||
min_fname_arg_count = 2
|
||||
|
||||
compat_args = {"foo": None, "bar": None, "baz": None}
|
||||
kwargs = {"foo": None, "bar": None}
|
||||
args = (None,) # duplicate value for "foo"
|
||||
|
||||
msg = rf"{_fname}\(\) got multiple values for keyword argument 'foo'"
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
validate_args_and_kwargs(_fname, args, kwargs, min_fname_arg_count, compat_args)
|
||||
|
||||
|
||||
def test_validation(_fname):
|
||||
# No exceptions should be raised.
|
||||
compat_args = {"foo": 1, "bar": None, "baz": -2}
|
||||
kwargs = {"baz": -2}
|
||||
|
||||
args = (1, None)
|
||||
min_fname_arg_count = 2
|
||||
|
||||
validate_args_and_kwargs(_fname, args, kwargs, min_fname_arg_count, compat_args)
|
@ -0,0 +1,40 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas.util._validators import validate_inclusive
|
||||
|
||||
import pandas as pd
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"invalid_inclusive",
|
||||
(
|
||||
"ccc",
|
||||
2,
|
||||
object(),
|
||||
None,
|
||||
np.nan,
|
||||
pd.NA,
|
||||
pd.DataFrame(),
|
||||
),
|
||||
)
|
||||
def test_invalid_inclusive(invalid_inclusive):
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match="Inclusive has to be either 'both', 'neither', 'left' or 'right'",
|
||||
):
|
||||
validate_inclusive(invalid_inclusive)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"valid_inclusive, expected_tuple",
|
||||
(
|
||||
("left", (True, False)),
|
||||
("right", (False, True)),
|
||||
("both", (True, True)),
|
||||
("neither", (False, False)),
|
||||
),
|
||||
)
|
||||
def test_valid_inclusive(valid_inclusive, expected_tuple):
|
||||
resultant_tuple = validate_inclusive(valid_inclusive)
|
||||
assert expected_tuple == resultant_tuple
|
@ -0,0 +1,69 @@
|
||||
import pytest
|
||||
|
||||
from pandas.util._validators import (
|
||||
validate_bool_kwarg,
|
||||
validate_kwargs,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def _fname():
|
||||
return "func"
|
||||
|
||||
|
||||
def test_bad_kwarg(_fname):
|
||||
good_arg = "f"
|
||||
bad_arg = good_arg + "o"
|
||||
|
||||
compat_args = {good_arg: "foo", bad_arg + "o": "bar"}
|
||||
kwargs = {good_arg: "foo", bad_arg: "bar"}
|
||||
|
||||
msg = rf"{_fname}\(\) got an unexpected keyword argument '{bad_arg}'"
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
validate_kwargs(_fname, kwargs, compat_args)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("i", range(1, 3))
|
||||
def test_not_all_none(i, _fname):
|
||||
bad_arg = "foo"
|
||||
msg = (
|
||||
rf"the '{bad_arg}' parameter is not supported "
|
||||
rf"in the pandas implementation of {_fname}\(\)"
|
||||
)
|
||||
|
||||
compat_args = {"foo": 1, "bar": "s", "baz": None}
|
||||
|
||||
kwarg_keys = ("foo", "bar", "baz")
|
||||
kwarg_vals = (2, "s", None)
|
||||
|
||||
kwargs = dict(zip(kwarg_keys[:i], kwarg_vals[:i]))
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
validate_kwargs(_fname, kwargs, compat_args)
|
||||
|
||||
|
||||
def test_validation(_fname):
|
||||
# No exceptions should be raised.
|
||||
compat_args = {"f": None, "b": 1, "ba": "s"}
|
||||
|
||||
kwargs = {"f": None, "b": 1}
|
||||
validate_kwargs(_fname, kwargs, compat_args)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", ["inplace", "copy"])
|
||||
@pytest.mark.parametrize("value", [1, "True", [1, 2, 3], 5.0])
|
||||
def test_validate_bool_kwarg_fail(name, value):
|
||||
msg = (
|
||||
f'For argument "{name}" expected type bool, '
|
||||
f"received type {type(value).__name__}"
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
validate_bool_kwarg(value, name)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", ["inplace", "copy"])
|
||||
@pytest.mark.parametrize("value", [True, False, None])
|
||||
def test_validate_bool_kwarg(name, value):
|
||||
assert validate_bool_kwarg(value, name) == value
|
Reference in New Issue
Block a user