github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/third_party/ouroboros/operator.py (about) 1 """ 2 Operator Interface 3 This module exports a set of functions corresponding to the intrinsic 4 operators of Python. For example, operator.add(x, y) is equivalent 5 to the expression x+y. The function names are those used for special 6 methods; variants without leading and trailing '__' are also provided 7 for convenience. 8 This is the pure Python implementation of the module. 9 """ 10 11 __all__ = ['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf', 12 'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand', 13 'iconcat', 'ifloordiv', 'ilshift', 'imod', 'imul', 'index', 14 'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift', 'is_', 15 'is_not', 'isub', 'itemgetter', 'itruediv', 'ixor', 'le', 16 'length_hint', 'lshift', 'lt', 'methodcaller', 'mod', 'mul', 'ne', 17 'neg', 'not_', 'or_', 'pos', 'pow', 'rshift', 'setitem', 'sub', 18 'truediv', 'truth', 'xor'] 19 20 from '__go__/math' import Abs as _abs 21 22 23 # Comparison Operations *******************************************************# 24 25 def lt(a, b): 26 "Same as a < b." 27 return a < b 28 29 def le(a, b): 30 "Same as a <= b." 31 return a <= b 32 33 def eq(a, b): 34 "Same as a == b." 35 return a == b 36 37 def ne(a, b): 38 "Same as a != b." 39 return a != b 40 41 def ge(a, b): 42 "Same as a >= b." 43 return a >= b 44 45 def gt(a, b): 46 "Same as a > b." 47 return a > b 48 49 # Logical Operations **********************************************************# 50 51 def not_(a): 52 "Same as not a." 53 return not a 54 55 def truth(a): 56 "Return True if a is true, False otherwise." 57 return True if a else False 58 59 def is_(a, b): 60 "Same as a is b." 61 return a is b 62 63 def is_not(a, b): 64 "Same as a is not b." 65 return a is not b 66 67 # Mathematical/Bitwise Operations *********************************************# 68 69 def abs(a): 70 "Same as abs(a)." 71 return _abs(a) 72 73 def add(a, b): 74 "Same as a + b." 75 return a + b 76 77 def and_(a, b): 78 "Same as a & b." 79 return a & b 80 81 def floordiv(a, b): 82 "Same as a // b." 83 return a // b 84 85 def index(a): 86 "Same as a.__index__()." 87 return a.__index__() 88 89 def inv(a): 90 "Same as ~a." 91 return ~a 92 invert = inv 93 94 def lshift(a, b): 95 "Same as a << b." 96 return a << b 97 98 def mod(a, b): 99 "Same as a % b." 100 return a % b 101 102 def mul(a, b): 103 "Same as a * b." 104 return a * b 105 106 def neg(a): 107 "Same as -a." 108 return -a 109 110 def or_(a, b): 111 "Same as a | b." 112 return a | b 113 114 def pos(a): 115 "Same as +a." 116 return +a 117 118 def pow(a, b): 119 "Same as a ** b." 120 return a**b 121 122 def rshift(a, b): 123 "Same as a >> b." 124 return a >> b 125 126 def sub(a, b): 127 "Same as a - b." 128 return a - b 129 130 def truediv(a, b): 131 "Same as a / b." 132 if type(a) == int or type(a) == long: 133 a = float(a) 134 return a / b 135 136 def xor(a, b): 137 "Same as a ^ b." 138 return a ^ b 139 140 # Sequence Operations *********************************************************# 141 142 def concat(a, b): 143 "Same as a + b, for a and b sequences." 144 if not hasattr(a, '__getitem__'): 145 msg = "'%s' object can't be concatenated" % type(a).__name__ 146 raise TypeError(msg) 147 return a + b 148 149 def contains(a, b): 150 "Same as b in a (note reversed operands)." 151 return b in a 152 153 def countOf(a, b): 154 "Return the number of times b occurs in a." 155 count = 0 156 for i in a: 157 if i == b: 158 count += 1 159 return count 160 161 def delitem(a, b): 162 "Same as del a[b]." 163 del a[b] 164 165 def getitem(a, b): 166 "Same as a[b]." 167 return a[b] 168 169 def indexOf(a, b): 170 "Return the first index of b in a." 171 for i, j in enumerate(a): 172 if j == b: 173 return i 174 else: 175 raise ValueError('sequence.index(x): x not in sequence') 176 177 def setitem(a, b, c): 178 "Same as a[b] = c." 179 a[b] = c 180 181 def length_hint(obj, default=0): 182 """ 183 Return an estimate of the number of items in obj. 184 This is useful for presizing containers when building from an iterable. 185 If the object supports len(), the result will be exact. Otherwise, it may 186 over- or under-estimate by an arbitrary amount. The result will be an 187 integer >= 0. 188 """ 189 if not isinstance(default, int): 190 msg = ("'%s' object cannot be interpreted as an integer" % 191 type(default).__name__) 192 raise TypeError(msg) 193 194 try: 195 return len(obj) 196 except TypeError: 197 pass 198 199 try: 200 hint = type(obj).__length_hint__ 201 except AttributeError: 202 return default 203 204 try: 205 val = hint(obj) 206 except TypeError: 207 return default 208 if val is NotImplemented: 209 return default 210 if not isinstance(val, int): 211 msg = ('__length_hint__ must be integer, not %s' % 212 type(val).__name__) 213 raise TypeError(msg) 214 if val < 0: 215 msg = '__length_hint__() should return >= 0' 216 raise ValueError(msg) 217 return val 218 219 # Generalized Lookup Objects **************************************************# 220 221 # TODO: class attrgetter: 222 class attrgetter(object): 223 """ 224 Return a callable object that fetches the given attribute(s) from its operand. 225 After f = attrgetter('name'), the call f(r) returns r.name. 226 After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date). 227 After h = attrgetter('name.first', 'name.last'), the call h(r) returns 228 (r.name.first, r.name.last). 229 """ 230 def __init__(self, attr, *attrs): 231 if not attrs: 232 if not isinstance(attr, str): 233 raise TypeError('attribute name must be a string') 234 names = attr.split('.') 235 def func(obj): 236 for name in names: 237 obj = getattr(obj, name) 238 return obj 239 self._call = func 240 else: 241 getters = tuple(map(attrgetter, (attr,) + attrs)) 242 def func(obj): 243 return tuple(getter(obj) for getter in getters) 244 self._call = func 245 246 def __call__(self, obj): 247 return self._call(obj) 248 249 # TODO: class itemgetter: 250 class itemgetter(object): 251 """ 252 Return a callable object that fetches the given item(s) from its operand. 253 After f = itemgetter(2), the call f(r) returns r[2]. 254 After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]) 255 """ 256 def __init__(self, item, *items): 257 if not items: 258 def func(obj): 259 return obj[item] 260 self._call = func 261 else: 262 items = (item,) + items 263 def func(obj): 264 return tuple(obj[i] for i in items) 265 self._call = func 266 267 def __call__(self, obj): 268 return self._call(obj) 269 270 # TODO: class methodcaller: 271 class methodcaller(object): 272 """ 273 Return a callable object that calls the given method on its operand. 274 After f = methodcaller('name'), the call f(r) returns r.name(). 275 After g = methodcaller('name', 'date', foo=1), the call g(r) returns 276 r.name('date', foo=1). 277 """ 278 279 def __init__(*args, **kwargs): 280 if len(args) < 2: 281 msg = "methodcaller needs at least one argument, the method name" 282 raise TypeError(msg) 283 self = args[0] 284 self._name = args[1] 285 self._args = args[2:] 286 self._kwargs = kwargs 287 288 def __call__(self, obj): 289 return getattr(obj, self._name)(*self._args, **self._kwargs) 290 291 # In-place Operations *********************************************************# 292 293 def iadd(a, b): 294 "Same as a += b." 295 a += b 296 return a 297 298 def iand(a, b): 299 "Same as a &= b." 300 a &= b 301 return a 302 303 def iconcat(a, b): 304 "Same as a += b, for a and b sequences." 305 if not hasattr(a, '__getitem__'): 306 msg = "'%s' object can't be concatenated" % type(a).__name__ 307 raise TypeError(msg) 308 a += b 309 return a 310 311 def ifloordiv(a, b): 312 "Same as a //= b." 313 a //= b 314 return a 315 316 def ilshift(a, b): 317 "Same as a <<= b." 318 a <<= b 319 return a 320 321 def imod(a, b): 322 "Same as a %= b." 323 a %= b 324 return a 325 326 def imul(a, b): 327 "Same as a *= b." 328 a *= b 329 return a 330 331 def ior(a, b): 332 "Same as a |= b." 333 a |= b 334 return a 335 336 def ipow(a, b): 337 "Same as a **= b." 338 a **= b 339 return a 340 341 def irshift(a, b): 342 "Same as a >>= b." 343 a >>= b 344 return a 345 346 def isub(a, b): 347 "Same as a -= b." 348 a -= b 349 return a 350 351 def itruediv(a, b): 352 "Same as a /= b." 353 if type(a) == int or type(a) == long: 354 a = float(a) 355 a /= b 356 return a 357 358 def ixor(a, b): 359 "Same as a ^= b." 360 a ^= b 361 return a 362 363 # TODO: https://github.com/google/grumpy/pull/263 364 #try: 365 # from _operator import * 366 #except ImportError: 367 # pass 368 #else: 369 # from _operator import __doc__ 370 371 # All of these "__func__ = func" assignments have to happen after importing 372 # from _operator to make sure they're set to the right function 373 __lt__ = lt 374 __le__ = le 375 __eq__ = eq 376 __ne__ = ne 377 __ge__ = ge 378 __gt__ = gt 379 __not__ = not_ 380 __abs__ = abs 381 __add__ = add 382 __and__ = and_ 383 __floordiv__ = floordiv 384 __index__ = index 385 __inv__ = inv 386 __invert__ = invert 387 __lshift__ = lshift 388 __mod__ = mod 389 __mul__ = mul 390 __neg__ = neg 391 __or__ = or_ 392 __pos__ = pos 393 __pow__ = pow 394 __rshift__ = rshift 395 __sub__ = sub 396 __truediv__ = truediv 397 __xor__ = xor 398 __concat__ = concat 399 __contains__ = contains 400 __delitem__ = delitem 401 __getitem__ = getitem 402 __setitem__ = setitem 403 __iadd__ = iadd 404 __iand__ = iand 405 __iconcat__ = iconcat 406 __ifloordiv__ = ifloordiv 407 __ilshift__ = ilshift 408 __imod__ = imod 409 __imul__ = imul 410 __ior__ = ior 411 __ipow__ = ipow 412 __irshift__ = irshift 413 __isub__ = isub 414 __itruediv__ = itruediv 415 __ixor__ = ixor