1"""
2Templates for invalid operations.
3"""
4from __future__ import annotations
5
6import operator
7
8import numpy as np
9
10
11def invalid_comparison(left, right, op) -> np.ndarray:
12 """
13 If a comparison has mismatched types and is not necessarily meaningful,
14 follow python3 conventions by:
15
16 - returning all-False for equality
17 - returning all-True for inequality
18 - raising TypeError otherwise
19
20 Parameters
21 ----------
22 left : array-like
23 right : scalar, array-like
24 op : operator.{eq, ne, lt, le, gt}
25
26 Raises
27 ------
28 TypeError : on inequality comparisons
29 """
30 if op is operator.eq:
31 res_values = np.zeros(left.shape, dtype=bool)
32 elif op is operator.ne:
33 res_values = np.ones(left.shape, dtype=bool)
34 else:
35 typ = type(right).__name__
36 raise TypeError(f"Invalid comparison between dtype={left.dtype} and {typ}")
37 return res_values
38
39
40def make_invalid_op(name: str):
41 """
42 Return a binary method that always raises a TypeError.
43
44 Parameters
45 ----------
46 name : str
47
48 Returns
49 -------
50 invalid_op : function
51 """
52
53 def invalid_op(self, other=None):
54 typ = type(self).__name__
55 raise TypeError(f"cannot perform {name} with this index type: {typ}")
56
57 invalid_op.__name__ = name
58 return invalid_op