|
14 | 14 | from pandas.core.computation.expressions import _MIN_ELEMENTS, NUMEXPR_INSTALLED
|
15 | 15 | from pandas.tests.frame.common import _check_mixed_float, _check_mixed_int
|
16 | 16 |
|
| 17 | + |
| 18 | +class DummyElement: |
| 19 | + def __init__(self, value, dtype): |
| 20 | + self.value = value |
| 21 | + self.dtype = np.dtype(dtype) |
| 22 | + |
| 23 | + def __array__(self): |
| 24 | + return np.array(self.value, dtype=self.dtype) |
| 25 | + |
| 26 | + def __str__(self) -> str: |
| 27 | + return f"DummyElement({self.value}, {self.dtype})" |
| 28 | + |
| 29 | + def __repr__(self) -> str: |
| 30 | + return str(self) |
| 31 | + |
| 32 | + def astype(self, dtype, copy=False): |
| 33 | + self.dtype = dtype |
| 34 | + return self |
| 35 | + |
| 36 | + def view(self, dtype): |
| 37 | + return type(self)(self.value.view(dtype), dtype) |
| 38 | + |
| 39 | + def any(self, axis=None): |
| 40 | + return bool(self.value) |
| 41 | + |
| 42 | + |
17 | 43 | # -------------------------------------------------------------------
|
18 | 44 | # Comparisons
|
19 | 45 |
|
@@ -782,6 +808,77 @@ def test_frame_with_frame_reindex(self):
|
782 | 808 | )
|
783 | 809 | tm.assert_frame_equal(result, expected)
|
784 | 810 |
|
| 811 | + @pytest.mark.parametrize( |
| 812 | + "value, dtype", |
| 813 | + [ |
| 814 | + (1, "i8"), |
| 815 | + (1.0, "f8"), |
| 816 | + (2 ** 63, "f8"), |
| 817 | + (1j, "complex128"), |
| 818 | + (2 ** 63, "complex128"), |
| 819 | + (True, "bool"), |
| 820 | + (np.timedelta64(20, "ns"), "<m8[ns]"), |
| 821 | + (np.datetime64(20, "ns"), "<M8[ns]"), |
| 822 | + ], |
| 823 | + ) |
| 824 | + @pytest.mark.parametrize( |
| 825 | + "op", |
| 826 | + [ |
| 827 | + operator.add, |
| 828 | + operator.sub, |
| 829 | + operator.mul, |
| 830 | + operator.truediv, |
| 831 | + operator.mod, |
| 832 | + operator.pow, |
| 833 | + ], |
| 834 | + ids=lambda x: x.__name__, |
| 835 | + ) |
| 836 | + def test_binop_other(self, op, value, dtype): |
| 837 | + skip = { |
| 838 | + (operator.add, "bool"), |
| 839 | + (operator.sub, "bool"), |
| 840 | + (operator.mul, "bool"), |
| 841 | + (operator.truediv, "bool"), |
| 842 | + (operator.mod, "i8"), |
| 843 | + (operator.mod, "complex128"), |
| 844 | + (operator.pow, "bool"), |
| 845 | + } |
| 846 | + if (op, dtype) in skip: |
| 847 | + pytest.skip(f"Invalid combination {op},{dtype}") |
| 848 | + |
| 849 | + e = DummyElement(value, dtype) |
| 850 | + s = DataFrame({"A": [e.value, e.value]}, dtype=e.dtype) |
| 851 | + |
| 852 | + invalid = { |
| 853 | + (operator.pow, "<M8[ns]"), |
| 854 | + (operator.mod, "<M8[ns]"), |
| 855 | + (operator.truediv, "<M8[ns]"), |
| 856 | + (operator.mul, "<M8[ns]"), |
| 857 | + (operator.add, "<M8[ns]"), |
| 858 | + (operator.pow, "<m8[ns]"), |
| 859 | + (operator.mul, "<m8[ns]"), |
| 860 | + } |
| 861 | + |
| 862 | + if (op, dtype) in invalid: |
| 863 | + msg = ( |
| 864 | + None |
| 865 | + if (dtype == "<M8[ns]" and op == operator.add) |
| 866 | + or (dtype == "<m8[ns]" and op == operator.mul) |
| 867 | + else ( |
| 868 | + f"cannot perform __{op.__name__}__ with this " |
| 869 | + "index type: (DatetimeArray|TimedeltaArray)" |
| 870 | + ) |
| 871 | + ) |
| 872 | + |
| 873 | + with pytest.raises(TypeError, match=msg): |
| 874 | + op(s, e.value) |
| 875 | + else: |
| 876 | + # FIXME: Since dispatching to Series, this test no longer |
| 877 | + # asserts anything meaningful |
| 878 | + result = op(s, e.value).dtypes |
| 879 | + expected = op(s, value).dtypes |
| 880 | + tm.assert_series_equal(result, expected) |
| 881 | + |
785 | 882 |
|
786 | 883 | def test_frame_with_zero_len_series_corner_cases():
|
787 | 884 | # GH#28600
|
|
0 commit comments