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