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', '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 times b occurs in a."
159    count = 0
160    for i in a:
161        if 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 == 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# Generalized Lookup Objects **************************************************#
225
226class attrgetter:
227    """
228    Return a callable object that fetches the given attribute(s) from its operand.
229    After f = attrgetter('name'), the call f(r) returns r.name.
230    After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).
231    After h = attrgetter('name.first', 'name.last'), the call h(r) returns
232    (r.name.first, r.name.last).
233    """
234    __slots__ = ('_attrs', '_call')
235
236    def __init__(self, attr, *attrs):
237        if not attrs:
238            if not isinstance(attr, str):
239                raise TypeError('attribute name must be a string')
240            self._attrs = (attr,)
241            names = attr.split('.')
242            def func(obj):
243                for name in names:
244                    obj = getattr(obj, name)
245                return obj
246            self._call = func
247        else:
248            self._attrs = (attr,) + attrs
249            getters = tuple(map(attrgetter, self._attrs))
250            def func(obj):
251                return tuple(getter(obj) for getter in getters)
252            self._call = func
253
254    def __call__(self, obj):
255        return self._call(obj)
256
257    def __repr__(self):
258        return '%s.%s(%s)' % (self.__class__.__module__,
259                              self.__class__.__qualname__,
260                              ', '.join(map(repr, self._attrs)))
261
262    def __reduce__(self):
263        return self.__class__, self._attrs
264
265class itemgetter:
266    """
267    Return a callable object that fetches the given item(s) from its operand.
268    After f = itemgetter(2), the call f(r) returns r[2].
269    After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])
270    """
271    __slots__ = ('_items', '_call')
272
273    def __init__(self, item, *items):
274        if not items:
275            self._items = (item,)
276            def func(obj):
277                return obj[item]
278            self._call = func
279        else:
280            self._items = items = (item,) + items
281            def func(obj):
282                return tuple(obj[i] for i in items)
283            self._call = func
284
285    def __call__(self, obj):
286        return self._call(obj)
287
288    def __repr__(self):
289        return '%s.%s(%s)' % (self.__class__.__module__,
290                              self.__class__.__name__,
291                              ', '.join(map(repr, self._items)))
292
293    def __reduce__(self):
294        return self.__class__, self._items
295
296class methodcaller:
297    """
298    Return a callable object that calls the given method on its operand.
299    After f = methodcaller('name'), the call f(r) returns r.name().
300    After g = methodcaller('name', 'date', foo=1), the call g(r) returns
301    r.name('date', foo=1).
302    """
303    __slots__ = ('_name', '_args', '_kwargs')
304
305    def __init__(self, name, /, *args, **kwargs):
306        self._name = name
307        if not isinstance(self._name, str):
308            raise TypeError('method name must be a string')
309        self._args = args
310        self._kwargs = kwargs
311
312    def __call__(self, obj):
313        return getattr(obj, self._name)(*self._args, **self._kwargs)
314
315    def __repr__(self):
316        args = [repr(self._name)]
317        args.extend(map(repr, self._args))
318        args.extend('%s=%r' % (k, v) for k, v in self._kwargs.items())
319        return '%s.%s(%s)' % (self.__class__.__module__,
320                              self.__class__.__name__,
321                              ', '.join(args))
322
323    def __reduce__(self):
324        if not self._kwargs:
325            return self.__class__, (self._name,) + self._args
326        else:
327            from functools import partial
328            return partial(self.__class__, self._name, **self._kwargs), self._args
329
330
331# In-place Operations *********************************************************#
332
333def iadd(a, b):
334    "Same as a += b."
335    a += b
336    return a
337
338def iand(a, b):
339    "Same as a &= b."
340    a &= b
341    return a
342
343def iconcat(a, b):
344    "Same as a += b, for a and b sequences."
345    if not hasattr(a, '__getitem__'):
346        msg = "'%s' object can't be concatenated" % type(a).__name__
347        raise TypeError(msg)
348    a += b
349    return a
350
351def ifloordiv(a, b):
352    "Same as a //= b."
353    a //= b
354    return a
355
356def ilshift(a, b):
357    "Same as a <<= b."
358    a <<= b
359    return a
360
361def imod(a, b):
362    "Same as a %= b."
363    a %= b
364    return a
365
366def imul(a, b):
367    "Same as a *= b."
368    a *= b
369    return a
370
371def imatmul(a, b):
372    "Same as a @= b."
373    a @= b
374    return a
375
376def ior(a, b):
377    "Same as a |= b."
378    a |= b
379    return a
380
381def ipow(a, b):
382    "Same as a **= b."
383    a **=b
384    return a
385
386def irshift(a, b):
387    "Same as a >>= b."
388    a >>= b
389    return a
390
391def isub(a, b):
392    "Same as a -= b."
393    a -= b
394    return a
395
396def itruediv(a, b):
397    "Same as a /= b."
398    a /= b
399    return a
400
401def ixor(a, b):
402    "Same as a ^= b."
403    a ^= b
404    return a
405
406
407try:
408    from _operator import *
409except ImportError:
410    pass
411else:
412    from _operator import __doc__
413
414# All of these "__func__ = func" assignments have to happen after importing
415# from _operator to make sure they're set to the right function
416__lt__ = lt
417__le__ = le
418__eq__ = eq
419__ne__ = ne
420__ge__ = ge
421__gt__ = gt
422__not__ = not_
423__abs__ = abs
424__add__ = add
425__and__ = and_
426__floordiv__ = floordiv
427__index__ = index
428__inv__ = inv
429__invert__ = invert
430__lshift__ = lshift
431__mod__ = mod
432__mul__ = mul
433__matmul__ = matmul
434__neg__ = neg
435__or__ = or_
436__pos__ = pos
437__pow__ = pow
438__rshift__ = rshift
439__sub__ = sub
440__truediv__ = truediv
441__xor__ = xor
442__concat__ = concat
443__contains__ = contains
444__delitem__ = delitem
445__getitem__ = getitem
446__setitem__ = setitem
447__iadd__ = iadd
448__iand__ = iand
449__iconcat__ = iconcat
450__ifloordiv__ = ifloordiv
451__ilshift__ = ilshift
452__imod__ = imod
453__imul__ = imul
454__imatmul__ = imatmul
455__ior__ = ior
456__ipow__ = ipow
457__irshift__ = irshift
458__isub__ = isub
459__itruediv__ = itruediv
460__ixor__ = ixor
461