this repo has no description
at trunk 580 lines 11 kB view raw
1#!/usr/bin/env python3 2# Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 3""" 4Operator Interface 5 6This module exports a set of functions corresponding to the intrinsic 7operators of Python. For example, operator.add(x, y) is equivalent 8to the expression x+y. The function names are those used for special 9methods; variants without leading and trailing '__' are also provided 10for convenience. 11 12This is the pure Python implementation of the module. 13The Pyro runtime and C-API can delegate to this module to do some heavy lifting. 14""" 15 16from builtins import _sequence_repr, _type_name, abs 17 18from _builtins import _divmod, _int_check, _lt as lt, _str_check, _type 19 20 21__all__ = [ 22 "abs", 23 "add", 24 "and_", 25 "attrgetter", 26 "concat", 27 "contains", 28 "countOf", 29 "delitem", 30 "eq", 31 "floordiv", 32 "ge", 33 "getitem", 34 "gt", 35 "iadd", 36 "iand", 37 "iconcat", 38 "ifloordiv", 39 "ilshift", 40 "imatmul", 41 "imod", 42 "imul", 43 "index", 44 "indexOf", 45 "inv", 46 "invert", 47 "ior", 48 "ipow", 49 "irshift", 50 "is_", 51 "is_not", 52 "isub", 53 "itemgetter", 54 "itruediv", 55 "ixor", 56 "le", 57 "length_hint", 58 "lshift", 59 "lt", 60 "matmul", 61 "methodcaller", 62 "mod", 63 "mul", 64 "ne", 65 "neg", 66 "not_", 67 "or_", 68 "pos", 69 "pow", 70 "rshift", 71 "setitem", 72 "sub", 73 "truediv", 74 "truth", 75 "xor", 76] 77 78 79# Comparison Operations *******************************************************# 80 81 82def eq(a, b): 83 "Same as a == b." 84 return a == b 85 86 87def ge(a, b): 88 "Same as a >= b." 89 return a >= b 90 91 92def gt(a, b): 93 "Same as a > b." 94 return a > b 95 96 97def le(a, b): 98 "Same as a <= b." 99 return a <= b 100 101 102def ne(a, b): 103 "Same as a != b." 104 return a != b 105 106 107# Logical Operations **********************************************************# 108 109 110def not_(a): 111 "Same as not a." 112 return not a 113 114 115def truth(a): 116 "Return True if a is true, False otherwise." 117 return True if a else False 118 119 120def is_(a, b): 121 "Same as a is b." 122 return a is b 123 124 125def is_not(a, b): 126 "Same as a is not b." 127 return a is not b 128 129 130# Mathematical/Bitwise Operations *********************************************# 131 132 133def add(a, b): 134 "Same as a + b." 135 return a + b 136 137 138def and_(a, b): 139 "Same as a & b." 140 return a & b 141 142 143def divmod(a, b): 144 "Same as divmod(a, b)." 145 return _divmod(a, b) 146 147 148def floordiv(a, b): 149 "Same as a // b." 150 return a // b 151 152 153def index(a): 154 "Same as a.__index__()." 155 return a.__index__() 156 157 158def inv(a): 159 "Same as ~a." 160 return ~a 161 162 163invert = inv 164 165 166def lshift(a, b): 167 "Same as a << b." 168 return a << b 169 170 171def mod(a, b): 172 "Same as a % b." 173 return a % b 174 175 176def mul(a, b): 177 "Same as a * b." 178 return a * b 179 180 181def matmul(a, b): 182 "Same as a @ b." 183 return a @ b 184 185 186def neg(a): 187 "Same as -a." 188 return -a 189 190 191def or_(a, b): 192 "Same as a | b." 193 return a | b 194 195 196def pos(a): 197 "Same as +a." 198 return +a 199 200 201def pow(a, b): 202 "Same as a ** b." 203 return a ** b 204 205 206def rshift(a, b): 207 "Same as a >> b." 208 return a >> b 209 210 211def sub(a, b): 212 "Same as a - b." 213 return a - b 214 215 216def truediv(a, b): 217 "Same as a / b." 218 return a / b 219 220 221def xor(a, b): 222 "Same as a ^ b." 223 return a ^ b 224 225 226# Sequence Operations *********************************************************# 227 228 229def concat(a, b): 230 "Same as a + b, for a and b sequences." 231 if not hasattr(a, "__getitem__"): 232 raise TypeError(f"'{_type(a).__name__}' object can't be concatenated") 233 return a + b 234 235 236def contains(a, b): 237 "Same as b in a (note reversed operands)." 238 return b in a 239 240 241def countOf(a, b): 242 "Return the number of times b occurs in a." 243 count = 0 244 for i in a: 245 if i == b: 246 count += 1 247 return count 248 249 250def delitem(a, b): 251 "Same as del a[b]." 252 del a[b] 253 254 255def getitem(a, b): 256 "Same as a[b]." 257 return a[b] 258 259 260def indexOf(a, b): 261 "Return the first index of b in a." 262 for i, j in enumerate(a): 263 if j == b: 264 return i 265 else: 266 raise ValueError("sequence.index(x): x not in sequence") 267 268 269def setitem(a, b, c): 270 "Same as a[b] = c." 271 a[b] = c 272 273 274def length_hint(obj, default=0): 275 """ 276 Return an estimate of the number of items in obj. 277 This is useful for presizing containers when building from an iterable. 278 279 If the object supports len(), the result will be exact. Otherwise, it may 280 over- or under-estimate by an arbitrary amount. The result will be an 281 integer >= 0. 282 """ 283 if not _int_check(default): 284 raise TypeError( 285 f"'{_type(default).__name__}' object cannot be interpreted as an integer" 286 ) 287 288 try: 289 return len(obj) 290 except TypeError: 291 pass 292 293 try: 294 hint = _type(obj).__length_hint__ 295 except AttributeError: 296 return default 297 298 try: 299 val = hint(obj) 300 except TypeError: 301 return default 302 if val is NotImplemented: 303 return default 304 if not _int_check(val): 305 raise TypeError(f"__length_hint__ must be integer, not {_type(val).__name__}") 306 if val < 0: 307 raise ValueError("__length_hint__() should return >= 0") 308 return val 309 310 311# Generalized Lookup Objects **************************************************# 312 313 314class attrgetter: 315 """ 316 Return a callable object that fetches the given attribute(s) from its operand. 317 After f = attrgetter('name'), the call f(r) returns r.name. 318 After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date). 319 After h = attrgetter('name.first', 'name.last'), the call h(r) returns 320 (r.name.first, r.name.last). 321 """ 322 323 __slots__ = ("_attrs", "_call") 324 325 def __init__(self, attr, *attrs): 326 if not attrs: 327 if not _str_check(attr): 328 raise TypeError("attribute name must be a string") 329 self._attrs = (attr,) 330 names = attr.split(".") 331 332 def func(obj): 333 for name in names: 334 obj = getattr(obj, name) 335 return obj 336 337 self._call = func 338 else: 339 self._attrs = (attr,) + attrs 340 getters = tuple(map(attrgetter, self._attrs)) 341 342 def func(obj): 343 return tuple(getter(obj) for getter in getters) 344 345 self._call = func 346 347 def __call__(self, obj): 348 return self._call(obj) 349 350 def __repr__(self): 351 return _sequence_repr(f"{_type_name(self.__class__)}(", self._attrs, ")") 352 353 def __reduce__(self): 354 return self.__class__, self._attrs 355 356 357class itemgetter: 358 """ 359 Return a callable object that fetches the given item(s) from its operand. 360 After f = itemgetter(2), the call f(r) returns r[2]. 361 After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]) 362 """ 363 364 __slots__ = ("_items", "_call") 365 366 def __init__(self, item, *items): 367 if not items: 368 self._items = (item,) 369 370 def func(obj): 371 return obj[item] 372 373 self._call = func 374 else: 375 self._items = items = (item,) + items 376 377 def func(obj): 378 return tuple(obj[i] for i in items) 379 380 self._call = func 381 382 def __call__(self, obj): 383 return self._call(obj) 384 385 def __repr__(self): 386 return _sequence_repr(f"{_type_name(self.__class__)}(", self._items, ")") 387 388 def __reduce__(self): 389 return self.__class__, self._items 390 391 392class methodcaller: 393 """ 394 Return a callable object that calls the given method on its operand. 395 After f = methodcaller('name'), the call f(r) returns r.name(). 396 After g = methodcaller('name', 'date', foo=1), the call g(r) returns 397 r.name('date', foo=1). 398 """ 399 400 __slots__ = ("_name", "_args", "_kwargs") 401 402 def __init__(self, name, /, *args, **kwargs): 403 self._name = name 404 if not _str_check(self._name): 405 raise TypeError("method name must be a string") 406 self._args = args 407 self._kwargs = kwargs 408 409 def __call__(self, obj): 410 return getattr(obj, self._name)(*self._args, **self._kwargs) 411 412 def __repr__(self): 413 args = [repr(self._name)] 414 args.extend(map(repr, self._args)) 415 args.extend("%s=%r" % (k, v) for k, v in self._kwargs.items()) 416 return f"{_type_name(self.__class__)}({','.join(args)})" 417 418 def __reduce__(self): 419 if not self._kwargs: 420 return self.__class__, (self._name,) + self._args 421 else: 422 from functools import partial 423 424 return partial(self.__class__, self._name, **self._kwargs), self._args 425 426 427# In-place Operations *********************************************************# 428 429 430def iadd(a, b): 431 "Same as a += b." 432 a += b 433 return a 434 435 436def iand(a, b): 437 "Same as a &= b." 438 a &= b 439 return a 440 441 442def iconcat(a, b): 443 "Same as a += b, for a and b sequences." 444 if not hasattr(a, "__getitem__"): 445 raise TypeError(f"'{_type(a).__name__}' object can't be concatenated") 446 a += b 447 return a 448 449 450def ifloordiv(a, b): 451 "Same as a //= b." 452 a //= b 453 return a 454 455 456def ilshift(a, b): 457 "Same as a <<= b." 458 a <<= b 459 return a 460 461 462def imod(a, b): 463 "Same as a %= b." 464 a %= b 465 return a 466 467 468def imul(a, b): 469 "Same as a *= b." 470 a *= b 471 return a 472 473 474def imatmul(a, b): 475 "Same as a @= b." 476 a @= b 477 return a 478 479 480def ior(a, b): 481 "Same as a |= b." 482 a |= b 483 return a 484 485 486def ipow(a, b): 487 "Same as a **= b." 488 a **= b 489 return a 490 491 492def irepeat(a, b): 493 "Same as a *= b, for a sequence." 494 if not hasattr(a, "__getitem__"): 495 raise TypeError(f"'{_type(a).__name__}' object can't be repeated") 496 a *= b 497 return a 498 499 500def irshift(a, b): 501 "Same as a >>= b." 502 a >>= b 503 return a 504 505 506def isub(a, b): 507 "Same as a -= b." 508 a -= b 509 return a 510 511 512def itruediv(a, b): 513 "Same as a /= b." 514 a /= b 515 return a 516 517 518def ixor(a, b): 519 "Same as a ^= b." 520 a ^= b 521 return a 522 523 524# TODO(wmeehan): uncomment once we have _operator 525""" 526try: 527 from _operator import * 528except ImportError: 529 pass 530else: 531 from _operator import __doc__ 532""" 533 534# All of these "__func__ = func" assignments have to happen after importing 535# from _operator to make sure they're set to the right function 536__lt__ = lt 537__le__ = le 538__eq__ = eq 539__ne__ = ne 540__ge__ = ge 541__gt__ = gt 542__not__ = not_ 543__abs__ = abs 544__add__ = add 545__and__ = and_ 546__floordiv__ = floordiv 547__index__ = index 548__inv__ = inv 549__invert__ = invert 550__lshift__ = lshift 551__mod__ = mod 552__mul__ = mul 553__matmul__ = matmul 554__neg__ = neg 555__or__ = or_ 556__pos__ = pos 557__pow__ = pow 558__rshift__ = rshift 559__sub__ = sub 560__truediv__ = truediv 561__xor__ = xor 562__concat__ = concat 563__contains__ = contains 564__delitem__ = delitem 565__getitem__ = getitem 566__setitem__ = setitem 567__iadd__ = iadd 568__iand__ = iand 569__iconcat__ = iconcat 570__ifloordiv__ = ifloordiv 571__ilshift__ = ilshift 572__imod__ = imod 573__imul__ = imul 574__imatmul__ = imatmul 575__ior__ = ior 576__ipow__ = ipow 577__irshift__ = irshift 578__isub__ = isub 579__itruediv__ = itruediv 580__ixor__ = ixor