this repo has no description
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