3 # © Copyright 2021-2022, Scott Gasch
5 """This is the base class of :class:`SmartFuture`. It is essentially
6 a class that tries to have every Python __dunder__ method defined
7 reasonably for it such that, when it is used in a manner that requires
8 its value to be known, it calls a `resolve` method to wait for the
13 from abc import ABC, abstractmethod
14 from typing import Any, Generic, TypeVar
16 # This module is commonly used by others in here and should avoid
17 # taking any unnecessary dependencies back on them.
22 class DeferredOperand(ABC, Generic[T]):
23 """A wrapper around an operand whose value is deferred until it is
24 needed (i.e. accessed). See the subclass :class:`SmartFuture` for
25 an example usage and/or a more useful patten.
29 def _resolve(self, timeout=None) -> T:
33 def resolve(x: Any) -> Any:
34 while isinstance(x, DeferredOperand):
38 def __lt__(self, other: Any) -> bool:
39 return DeferredOperand.resolve(self) < DeferredOperand.resolve(other)
41 def __le__(self, other: Any) -> bool:
42 return DeferredOperand.resolve(self) <= DeferredOperand.resolve(other)
44 def __eq__(self, other: Any) -> bool:
45 return DeferredOperand.resolve(self) == DeferredOperand.resolve(other)
47 def __ne__(self, other: Any) -> bool:
48 return DeferredOperand.resolve(self) != DeferredOperand.resolve(other)
50 def __gt__(self, other: Any) -> bool:
51 return DeferredOperand.resolve(self) > DeferredOperand.resolve(other)
53 def __ge__(self, other: Any) -> bool:
54 return DeferredOperand.resolve(self) >= DeferredOperand.resolve(other)
56 def __not__(self) -> bool:
57 return not DeferredOperand.resolve(self)
59 def bool(self) -> bool:
60 return DeferredOperand.resolve(self)
62 def __add__(self, other: Any) -> T:
63 return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
65 def __iadd__(self, other: Any) -> T:
66 return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
68 def __radd__(self, other: Any) -> T:
69 return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
71 def __sub__(self, other: Any) -> T:
72 return DeferredOperand.resolve(self) - DeferredOperand.resolve(other)
74 def __mul__(self, other: Any) -> T:
75 return DeferredOperand.resolve(self) * DeferredOperand.resolve(other)
77 def __pow__(self, other: Any) -> T:
78 return DeferredOperand.resolve(self) ** DeferredOperand.resolve(other)
80 def __truediv__(self, other: Any) -> Any:
81 return DeferredOperand.resolve(self) / DeferredOperand.resolve(other)
83 def __floordiv__(self, other: Any) -> T:
84 return DeferredOperand.resolve(self) // DeferredOperand.resolve(other)
86 def __contains__(self, other):
87 return DeferredOperand.resolve(other) in DeferredOperand.resolve(self)
89 def and_(self, other):
90 return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
93 return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
96 return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
99 return ~(DeferredOperand.resolve(self))
101 def is_(self, other):
102 return DeferredOperand.resolve(self) is DeferredOperand.resolve(other)
104 def is_not(self, other):
105 return DeferredOperand.resolve(self) is not DeferredOperand.resolve(other)
108 return abs(DeferredOperand.resolve(self))
110 def setitem(self, k, v):
111 DeferredOperand.resolve(self)[DeferredOperand.resolve(k)] = v
113 def delitem(self, k):
114 del DeferredOperand.resolve(self)[DeferredOperand.resolve(k)]
116 def getitem(self, k):
117 return DeferredOperand.resolve(self)[DeferredOperand.resolve(k)]
119 def lshift(self, other):
120 return DeferredOperand.resolve(self) << DeferredOperand.resolve(other)
122 def rshift(self, other):
123 return DeferredOperand.resolve(self) >> DeferredOperand.resolve(other)
125 def mod(self, other):
126 return DeferredOperand.resolve(self) % DeferredOperand.resolve(other)
128 def matmul(self, other):
129 return DeferredOperand.resolve(self) @ DeferredOperand.resolve(other)
132 return -(DeferredOperand.resolve(self))
135 return +(DeferredOperand.resolve(self))
138 return DeferredOperand.resolve(self)
141 return DeferredOperand.resolve(self).__hash__()
144 return DeferredOperand.resolve(self)()
147 return DeferredOperand.resolve(self).__iter__()
149 def __repr__(self) -> str:
150 return DeferredOperand.resolve(self).__repr__()
152 def __bytes__(self) -> bytes:
153 return DeferredOperand.resolve(self).__bytes__()
155 def __int__(self) -> int:
156 return int(DeferredOperand.resolve(self))
158 def __float__(self) -> float:
159 return float(DeferredOperand.resolve(self))
161 def __getattr__(self, method_name):
162 def method(*args, **kwargs):
163 return getattr(DeferredOperand.resolve(self), method_name)(*args, **kwargs)