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