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