123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- import operator
- import numpy as np
- import pytest
- import pandas as pd
- import pandas._testing as tm
- @pytest.fixture
- def data():
- """Fixture returning boolean array with valid and missing values."""
- return pd.array(
- [True, False] * 4 + [np.nan] + [True, False] * 44 + [np.nan] + [True, False],
- dtype="boolean",
- )
- @pytest.fixture
- def left_array():
- """Fixture returning boolean array with valid and missing values."""
- return pd.array([True] * 3 + [False] * 3 + [None] * 3, dtype="boolean")
- @pytest.fixture
- def right_array():
- """Fixture returning boolean array with valid and missing values."""
- return pd.array([True, False, None] * 3, dtype="boolean")
- # Basic test for the arithmetic array ops
- # -----------------------------------------------------------------------------
- @pytest.mark.parametrize(
- "opname, exp",
- [
- ("add", [True, True, None, True, False, None, None, None, None]),
- ("mul", [True, False, None, False, False, None, None, None, None]),
- ],
- ids=["add", "mul"],
- )
- def test_add_mul(left_array, right_array, opname, exp):
- op = getattr(operator, opname)
- result = op(left_array, right_array)
- expected = pd.array(exp, dtype="boolean")
- tm.assert_extension_array_equal(result, expected)
- def test_sub(left_array, right_array):
- msg = (
- r"numpy boolean subtract, the `-` operator, is (?:deprecated|not supported), "
- r"use the bitwise_xor, the `\^` operator, or the logical_xor function instead\."
- )
- with pytest.raises(TypeError, match=msg):
- left_array - right_array
- def test_div(left_array, right_array):
- msg = "operator '.*' not implemented for bool dtypes"
- with pytest.raises(NotImplementedError, match=msg):
- # check that we are matching the non-masked Series behavior
- pd.Series(left_array._data) / pd.Series(right_array._data)
- with pytest.raises(NotImplementedError, match=msg):
- left_array / right_array
- @pytest.mark.parametrize(
- "opname",
- [
- "floordiv",
- "mod",
- "pow",
- ],
- )
- def test_op_int8(left_array, right_array, opname):
- op = getattr(operator, opname)
- if opname != "mod":
- msg = "operator '.*' not implemented for bool dtypes"
- with pytest.raises(NotImplementedError, match=msg):
- result = op(left_array, right_array)
- return
- result = op(left_array, right_array)
- expected = op(left_array.astype("Int8"), right_array.astype("Int8"))
- tm.assert_extension_array_equal(result, expected)
- # Test generic characteristics / errors
- # -----------------------------------------------------------------------------
- def test_error_invalid_values(data, all_arithmetic_operators):
- # invalid ops
- op = all_arithmetic_operators
- s = pd.Series(data)
- ops = getattr(s, op)
- # invalid scalars
- msg = (
- "did not contain a loop with signature matching types|"
- "BooleanArray cannot perform the operation|"
- "not supported for the input types, and the inputs could not be safely coerced "
- "to any supported types according to the casting rule ''safe''"
- )
- with pytest.raises(TypeError, match=msg):
- ops("foo")
- msg = "|".join(
- [
- r"unsupported operand type\(s\) for",
- "Concatenation operation is not implemented for NumPy arrays",
- ]
- )
- with pytest.raises(TypeError, match=msg):
- ops(pd.Timestamp("20180101"))
- # invalid array-likes
- if op not in ("__mul__", "__rmul__"):
- # TODO(extension) numpy's mul with object array sees booleans as numbers
- msg = "|".join(
- [
- r"unsupported operand type\(s\) for",
- "can only concatenate str",
- "not all arguments converted during string formatting",
- ]
- )
- with pytest.raises(TypeError, match=msg):
- ops(pd.Series("foo", index=s.index))
|