ACL uses enums, some more tests, other stuff.
[python_utils.git] / deferred_operand.py
1 #!/usr/bin/env python3
2
3 from abc import ABC, abstractmethod
4 from typing import Any, Generic, TypeVar
5
6 # This module is commonly used by others in here and should avoid
7 # taking any unnecessary dependencies back on them.
8
9 T = TypeVar('T')
10
11
12 class DeferredOperand(ABC, Generic[T]):
13     """A wrapper around an operand whose value is deferred until it is
14     needed.  See subclass SmartFuture for an example usage.
15     """
16
17     @abstractmethod
18     def _resolve(self) -> T:
19         pass
20
21     @staticmethod
22     def resolve(x: Any) -> Any:
23         while isinstance(x, DeferredOperand):
24             x = x._resolve()
25         return x
26
27     def __lt__(self, other: Any) -> bool:
28         return DeferredOperand.resolve(self) < DeferredOperand.resolve(other)
29
30     def __le__(self, other: Any) -> bool:
31         return DeferredOperand.resolve(self) <= DeferredOperand.resolve(other)
32
33     def __eq__(self, other: Any) -> bool:
34         return DeferredOperand.resolve(self) == DeferredOperand.resolve(other)
35
36     def __ne__(self, other: Any) -> bool:
37         return DeferredOperand.resolve(self) != DeferredOperand.resolve(other)
38
39     def __gt__(self, other: Any) -> bool:
40         return DeferredOperand.resolve(self) > DeferredOperand.resolve(other)
41
42     def __ge__(self, other: Any) -> bool:
43         return DeferredOperand.resolve(self) >= DeferredOperand.resolve(other)
44
45     def __not__(self) -> bool:
46         return not DeferredOperand.resolve(self)
47
48     def bool(self) -> bool:
49         return DeferredOperand.resolve(self)
50
51     def __add__(self, other: Any) -> T:
52         return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
53
54     def __iadd__(self, other: Any) -> T:
55         return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
56
57     def __radd__(self, other: Any) -> T:
58         return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
59
60     def __sub__(self, other: Any) -> T:
61         return DeferredOperand.resolve(self) - DeferredOperand.resolve(other)
62
63     def __mul__(self, other: Any) -> T:
64         return DeferredOperand.resolve(self) * DeferredOperand.resolve(other)
65
66     def __pow__(self, other: Any) -> T:
67         return DeferredOperand.resolve(self) ** DeferredOperand.resolve(other)
68
69     def __truediv__(self, other: Any) -> Any:
70         return DeferredOperand.resolve(self) / DeferredOperand.resolve(other)
71
72     def __floordiv__(self, other: Any) -> T:
73         return DeferredOperand.resolve(self) // DeferredOperand.resolve(other)
74
75     def __contains__(self, other):
76         return DeferredOperand.resolve(other) in DeferredOperand.resolve(self)
77
78     def and_(self, other):
79         return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
80
81     def or_(self, other):
82         return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
83
84     def xor(self, other):
85         return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
86
87     def invert(self):
88         return ~(DeferredOperand.resolve(self))
89
90     def is_(self, other):
91         return DeferredOperand.resolve(self) is DeferredOperand.resolve(other)
92
93     def is_not(self, other):
94         return DeferredOperand.resolve(self) is not DeferredOperand.resolve(other)
95
96     def __abs__(self):
97         return abs(DeferredOperand.resolve(self))
98
99     def setitem(self, k, v):
100         DeferredOperand.resolve(self)[DeferredOperand.resolve(k)] = v
101
102     def delitem(self, k):
103         del DeferredOperand.resolve(self)[DeferredOperand.resolve(k)]
104
105     def getitem(self, k):
106         return DeferredOperand.resolve(self)[DeferredOperand.resolve(k)]
107
108     def lshift(self, other):
109         return DeferredOperand.resolve(self) << DeferredOperand.resolve(other)
110
111     def rshift(self, other):
112         return DeferredOperand.resolve(self) >> DeferredOperand.resolve(other)
113
114     def mod(self, other):
115         return DeferredOperand.resolve(self) % DeferredOperand.resolve(other)
116
117     def matmul(self, other):
118         return DeferredOperand.resolve(self) @ DeferredOperand.resolve(other)
119
120     def neg(self):
121         return -(DeferredOperand.resolve(self))
122
123     def pos(self):
124         return +(DeferredOperand.resolve(self))
125
126     def truth(self):
127         return DeferredOperand.resolve(self)
128
129     def __hash__(self):
130         return DeferredOperand.resolve(self).__hash__()
131
132     def __call__(self):
133         return DeferredOperand.resolve(self)()
134
135     def __iter__(self):
136         return DeferredOperand.resolve(self).__iter__()
137
138     def __repr__(self) -> str:
139         return DeferredOperand.resolve(self).__repr__()
140
141     def __bytes__(self) -> bytes:
142         return DeferredOperand.resolve(self).__bytes__()
143
144     def __int__(self) -> int:
145         return int(DeferredOperand.resolve(self))
146
147     def __float__(self) -> float:
148         return float(DeferredOperand.resolve(self))
149
150     def __getattr__(self, method_name):
151         def method(*args, **kwargs):
152             return getattr(DeferredOperand.resolve(self), method_name)(
153                 *args, **kwargs
154             )
155         return method