Updated script that can be controled by Nodejs web app
This commit is contained in:
26
lib/python3.13/site-packages/pandas/tests/util/conftest.py
Normal file
26
lib/python3.13/site-packages/pandas/tests/util/conftest.py
Normal file
@ -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")
|
90
lib/python3.13/site-packages/pandas/tests/util/test_doc.py
Normal file
90
lib/python3.13/site-packages/pandas/tests/util/test_doc.py
Normal file
@ -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
|
417
lib/python3.13/site-packages/pandas/tests/util/test_hashing.py
Normal file
417
lib/python3.13/site-packages/pandas/tests/util/test_hashing.py
Normal file
@ -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)
|
12
lib/python3.13/site-packages/pandas/tests/util/test_numba.py
Normal file
12
lib/python3.13/site-packages/pandas/tests/util/test_numba.py
Normal file
@ -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
|
58
lib/python3.13/site-packages/pandas/tests/util/test_util.py
Normal file
58
lib/python3.13/site-packages/pandas/tests/util/test_util.py
Normal 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