Issue #16694: Add a pure Python implementation of the operator module.
Patch by Zachary Ware.
This commit is contained in:
parent
c9f5ca232a
commit
a85017fbe3
|
@ -4,7 +4,7 @@ Implements the HMAC algorithm as described by RFC 2104.
|
|||
"""
|
||||
|
||||
import warnings as _warnings
|
||||
from operator import _compare_digest as compare_digest
|
||||
from _operator import _compare_digest as compare_digest
|
||||
|
||||
trans_5C = bytes((x ^ 0x5C) for x in range(256))
|
||||
trans_36 = bytes((x ^ 0x36) for x in range(256))
|
||||
|
|
|
@ -0,0 +1,412 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Operator Interface
|
||||
|
||||
This module exports a set of functions corresponding to the intrinsic
|
||||
operators of Python. For example, operator.add(x, y) is equivalent
|
||||
to the expression x+y. The function names are those used for special
|
||||
methods; variants without leading and trailing '__' are also provided
|
||||
for convenience.
|
||||
|
||||
This is the pure Python implementation of the module.
|
||||
"""
|
||||
|
||||
__all__ = ['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf',
|
||||
'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand',
|
||||
'iconcat', 'ifloordiv', 'ilshift', 'imod', 'imul', 'index',
|
||||
'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift', 'is_',
|
||||
'is_not', 'isub', 'itemgetter', 'itruediv', 'ixor', 'le',
|
||||
'length_hint', 'lshift', 'lt', 'methodcaller', 'mod', 'mul', 'ne',
|
||||
'neg', 'not_', 'or_', 'pos', 'pow', 'rshift', 'setitem', 'sub',
|
||||
'truediv', 'truth', 'xor']
|
||||
|
||||
from builtins import abs as _abs
|
||||
|
||||
|
||||
# Comparison Operations *******************************************************#
|
||||
|
||||
def lt(a, b):
|
||||
"Same as a < b."
|
||||
return a < b
|
||||
|
||||
def le(a, b):
|
||||
"Same as a <= b."
|
||||
return a <= b
|
||||
|
||||
def eq(a, b):
|
||||
"Same as a == b."
|
||||
return a == b
|
||||
|
||||
def ne(a, b):
|
||||
"Same as a != b."
|
||||
return a != b
|
||||
|
||||
def ge(a, b):
|
||||
"Same as a >= b."
|
||||
return a >= b
|
||||
|
||||
def gt(a, b):
|
||||
"Same as a > b."
|
||||
return a > b
|
||||
|
||||
# Logical Operations **********************************************************#
|
||||
|
||||
def not_(a):
|
||||
"Same as not a."
|
||||
return not a
|
||||
|
||||
def truth(a):
|
||||
"Return True if a is true, False otherwise."
|
||||
return True if a else False
|
||||
|
||||
def is_(a, b):
|
||||
"Same as a is b."
|
||||
return a is b
|
||||
|
||||
def is_not(a, b):
|
||||
"Same as a is not b."
|
||||
return a is not b
|
||||
|
||||
# Mathematical/Bitwise Operations *********************************************#
|
||||
|
||||
def abs(a):
|
||||
"Same as abs(a)."
|
||||
return _abs(a)
|
||||
|
||||
def add(a, b):
|
||||
"Same as a + b."
|
||||
return a + b
|
||||
|
||||
def and_(a, b):
|
||||
"Same as a & b."
|
||||
return a & b
|
||||
|
||||
def floordiv(a, b):
|
||||
"Same as a // b."
|
||||
return a // b
|
||||
|
||||
def index(a):
|
||||
"Same as a.__index__()."
|
||||
return a.__index__()
|
||||
|
||||
def inv(a):
|
||||
"Same as ~a."
|
||||
return ~a
|
||||
invert = inv
|
||||
|
||||
def lshift(a, b):
|
||||
"Same as a << b."
|
||||
return a << b
|
||||
|
||||
def mod(a, b):
|
||||
"Same as a % b."
|
||||
return a % b
|
||||
|
||||
def mul(a, b):
|
||||
"Same as a * b."
|
||||
return a * b
|
||||
|
||||
def neg(a):
|
||||
"Same as -a."
|
||||
return -a
|
||||
|
||||
def or_(a, b):
|
||||
"Same as a | b."
|
||||
return a | b
|
||||
|
||||
def pos(a):
|
||||
"Same as +a."
|
||||
return +a
|
||||
|
||||
def pow(a, b):
|
||||
"Same as a ** b."
|
||||
return a ** b
|
||||
|
||||
def rshift(a, b):
|
||||
"Same as a >> b."
|
||||
return a >> b
|
||||
|
||||
def sub(a, b):
|
||||
"Same as a - b."
|
||||
return a - b
|
||||
|
||||
def truediv(a, b):
|
||||
"Same as a / b."
|
||||
return a / b
|
||||
|
||||
def xor(a, b):
|
||||
"Same as a ^ b."
|
||||
return a ^ b
|
||||
|
||||
# Sequence Operations *********************************************************#
|
||||
|
||||
def concat(a, b):
|
||||
"Same as a + b, for a and b sequences."
|
||||
if not hasattr(a, '__getitem__'):
|
||||
msg = "'%s' object can't be concatenated" % type(a).__name__
|
||||
raise TypeError(msg)
|
||||
return a + b
|
||||
|
||||
def contains(a, b):
|
||||
"Same as b in a (note reversed operands)."
|
||||
return b in a
|
||||
|
||||
def countOf(a, b):
|
||||
"Return the number of times b occurs in a."
|
||||
count = 0
|
||||
for i in a:
|
||||
if i == b:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def delitem(a, b):
|
||||
"Same as del a[b]."
|
||||
del a[b]
|
||||
|
||||
def getitem(a, b):
|
||||
"Same as a[b]."
|
||||
return a[b]
|
||||
|
||||
def indexOf(a, b):
|
||||
"Return the first index of b in a."
|
||||
for i, j in enumerate(a):
|
||||
if j == b:
|
||||
return i
|
||||
else:
|
||||
raise ValueError('sequence.index(x): x not in sequence')
|
||||
|
||||
def setitem(a, b, c):
|
||||
"Same as a[b] = c."
|
||||
a[b] = c
|
||||
|
||||
def length_hint(obj, default=0):
|
||||
"""
|
||||
Return an estimate of the number of items in obj.
|
||||
This is useful for presizing containers when building from an iterable.
|
||||
|
||||
If the object supports len(), the result will be exact. Otherwise, it may
|
||||
over- or under-estimate by an arbitrary amount. The result will be an
|
||||
integer >= 0.
|
||||
"""
|
||||
if not isinstance(default, int):
|
||||
msg = ("'%s' object cannot be interpreted as an integer" %
|
||||
type(default).__name__)
|
||||
raise TypeError(msg)
|
||||
|
||||
try:
|
||||
return len(obj)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
hint = type(obj).__length_hint__
|
||||
except AttributeError:
|
||||
return default
|
||||
|
||||
try:
|
||||
val = hint(obj)
|
||||
except TypeError:
|
||||
return default
|
||||
if val is NotImplemented:
|
||||
return default
|
||||
if not isinstance(val, int):
|
||||
msg = ('__length_hint__ must be integer, not %s' %
|
||||
type(val).__name__)
|
||||
raise TypeError(msg)
|
||||
if val < 0:
|
||||
msg = '__length_hint__() should return >= 0'
|
||||
raise ValueError(msg)
|
||||
return val
|
||||
|
||||
# Generalized Lookup Objects **************************************************#
|
||||
|
||||
class attrgetter:
|
||||
"""
|
||||
Return a callable object that fetches the given attribute(s) from its operand.
|
||||
After f=attrgetter('name'), the call f(r) returns r.name.
|
||||
After g=attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).
|
||||
After h=attrgetter('name.first', 'name.last'), the call h(r) returns
|
||||
(r.name.first, r.name.last).
|
||||
"""
|
||||
def __init__(self, attr, *attrs):
|
||||
if not attrs:
|
||||
if not isinstance(attr, str):
|
||||
raise TypeError('attribute name must be a string')
|
||||
names = attr.split('.')
|
||||
def func(obj):
|
||||
for name in names:
|
||||
obj = getattr(obj, name)
|
||||
return obj
|
||||
self._call = func
|
||||
else:
|
||||
getters = tuple(map(attrgetter, (attr,) + attrs))
|
||||
def func(obj):
|
||||
return tuple(getter(obj) for getter in getters)
|
||||
self._call = func
|
||||
|
||||
def __call__(self, obj):
|
||||
return self._call(obj)
|
||||
|
||||
class itemgetter:
|
||||
"""
|
||||
Return a callable object that fetches the given item(s) from its operand.
|
||||
After f=itemgetter(2), the call f(r) returns r[2].
|
||||
After g=itemgetter(2,5,3), the call g(r) returns (r[2], r[5], r[3])
|
||||
"""
|
||||
def __init__(self, item, *items):
|
||||
if not items:
|
||||
def func(obj):
|
||||
return obj[item]
|
||||
self._call = func
|
||||
else:
|
||||
items = (item,) + items
|
||||
def func(obj):
|
||||
return tuple(obj[i] for i in items)
|
||||
self._call = func
|
||||
|
||||
def __call__(self, obj):
|
||||
return self._call(obj)
|
||||
|
||||
class methodcaller:
|
||||
"""
|
||||
Return a callable object that calls the given method on its operand.
|
||||
After f = methodcaller('name'), the call f(r) returns r.name().
|
||||
After g = methodcaller('name', 'date', foo=1), the call g(r) returns
|
||||
r.name('date', foo=1).
|
||||
"""
|
||||
|
||||
def __init__(*args, **kwargs):
|
||||
if len(args) < 2:
|
||||
msg = "methodcaller needs at least one argument, the method name"
|
||||
raise TypeError(msg)
|
||||
self = args[0]
|
||||
self._name = args[1]
|
||||
self._args = args[2:]
|
||||
self._kwargs = kwargs
|
||||
|
||||
def __call__(self, obj):
|
||||
return getattr(obj, self._name)(*self._args, **self._kwargs)
|
||||
|
||||
# In-place Operations *********************************************************#
|
||||
|
||||
def iadd(a, b):
|
||||
"Same as a += b."
|
||||
a += b
|
||||
return a
|
||||
|
||||
def iand(a, b):
|
||||
"Same as a &= b."
|
||||
a &= b
|
||||
return a
|
||||
|
||||
def iconcat(a, b):
|
||||
"Same as a += b, for a and b sequences."
|
||||
if not hasattr(a, '__getitem__'):
|
||||
msg = "'%s' object can't be concatenated" % type(a).__name__
|
||||
raise TypeError(msg)
|
||||
a += b
|
||||
return a
|
||||
|
||||
def ifloordiv(a, b):
|
||||
"Same as a //= b."
|
||||
a //= b
|
||||
return a
|
||||
|
||||
def ilshift(a, b):
|
||||
"Same as a <<= b."
|
||||
a <<= b
|
||||
return a
|
||||
|
||||
def imod(a, b):
|
||||
"Same as a %= b."
|
||||
a %= b
|
||||
return a
|
||||
|
||||
def imul(a, b):
|
||||
"Same as a *= b."
|
||||
a *= b
|
||||
return a
|
||||
|
||||
def ior(a, b):
|
||||
"Same as a |= b."
|
||||
a |= b
|
||||
return a
|
||||
|
||||
def ipow(a, b):
|
||||
"Same as a **= b."
|
||||
a **=b
|
||||
return a
|
||||
|
||||
def irshift(a, b):
|
||||
"Same as a >>= b."
|
||||
a >>= b
|
||||
return a
|
||||
|
||||
def isub(a, b):
|
||||
"Same as a -= b."
|
||||
a -= b
|
||||
return a
|
||||
|
||||
def itruediv(a, b):
|
||||
"Same as a /= b."
|
||||
a /= b
|
||||
return a
|
||||
|
||||
def ixor(a, b):
|
||||
"Same as a ^= b."
|
||||
a ^= b
|
||||
return a
|
||||
|
||||
|
||||
try:
|
||||
from _operator import *
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
from _operator import __doc__
|
||||
|
||||
# All of these "__func__ = func" assignments have to happen after importing
|
||||
# from _operator to make sure they're set to the right function
|
||||
__lt__ = lt
|
||||
__le__ = le
|
||||
__eq__ = eq
|
||||
__ne__ = ne
|
||||
__ge__ = ge
|
||||
__gt__ = gt
|
||||
__not__ = not_
|
||||
__abs__ = abs
|
||||
__add__ = add
|
||||
__and__ = and_
|
||||
__floordiv__ = floordiv
|
||||
__index__ = index
|
||||
__inv__ = inv
|
||||
__invert__ = invert
|
||||
__lshift__ = lshift
|
||||
__mod__ = mod
|
||||
__mul__ = mul
|
||||
__neg__ = neg
|
||||
__or__ = or_
|
||||
__pos__ = pos
|
||||
__pow__ = pow
|
||||
__rshift__ = rshift
|
||||
__sub__ = sub
|
||||
__truediv__ = truediv
|
||||
__xor__ = xor
|
||||
__concat__ = concat
|
||||
__contains__ = contains
|
||||
__delitem__ = delitem
|
||||
__getitem__ = getitem
|
||||
__setitem__ = setitem
|
||||
__iadd__ = iadd
|
||||
__iand__ = iand
|
||||
__iconcat__ = iconcat
|
||||
__ifloordiv__ = ifloordiv
|
||||
__ilshift__ = ilshift
|
||||
__imod__ = imod
|
||||
__imul__ = imul
|
||||
__ior__ = ior
|
||||
__ipow__ = ipow
|
||||
__irshift__ = irshift
|
||||
__isub__ = isub
|
||||
__itruediv__ = itruediv
|
||||
__ixor__ = ixor
|
|
@ -1,8 +1,10 @@
|
|||
import operator
|
||||
import unittest
|
||||
|
||||
from test import support
|
||||
|
||||
py_operator = support.import_fresh_module('operator', blocked=['_operator'])
|
||||
c_operator = support.import_fresh_module('operator', fresh=['_operator'])
|
||||
|
||||
class Seq1:
|
||||
def __init__(self, lst):
|
||||
self.lst = lst
|
||||
|
@ -32,8 +34,9 @@ class Seq2(object):
|
|||
return other * self.lst
|
||||
|
||||
|
||||
class OperatorTestCase(unittest.TestCase):
|
||||
class OperatorTestCase:
|
||||
def test_lt(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.lt)
|
||||
self.assertRaises(TypeError, operator.lt, 1j, 2j)
|
||||
self.assertFalse(operator.lt(1, 0))
|
||||
|
@ -44,6 +47,7 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertTrue(operator.lt(1, 2.0))
|
||||
|
||||
def test_le(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.le)
|
||||
self.assertRaises(TypeError, operator.le, 1j, 2j)
|
||||
self.assertFalse(operator.le(1, 0))
|
||||
|
@ -54,6 +58,7 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertTrue(operator.le(1, 2.0))
|
||||
|
||||
def test_eq(self):
|
||||
operator = self.module
|
||||
class C(object):
|
||||
def __eq__(self, other):
|
||||
raise SyntaxError
|
||||
|
@ -67,6 +72,7 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertFalse(operator.eq(1, 2.0))
|
||||
|
||||
def test_ne(self):
|
||||
operator = self.module
|
||||
class C(object):
|
||||
def __ne__(self, other):
|
||||
raise SyntaxError
|
||||
|
@ -80,6 +86,7 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertTrue(operator.ne(1, 2.0))
|
||||
|
||||
def test_ge(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.ge)
|
||||
self.assertRaises(TypeError, operator.ge, 1j, 2j)
|
||||
self.assertTrue(operator.ge(1, 0))
|
||||
|
@ -90,6 +97,7 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertFalse(operator.ge(1, 2.0))
|
||||
|
||||
def test_gt(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.gt)
|
||||
self.assertRaises(TypeError, operator.gt, 1j, 2j)
|
||||
self.assertTrue(operator.gt(1, 0))
|
||||
|
@ -100,22 +108,26 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertFalse(operator.gt(1, 2.0))
|
||||
|
||||
def test_abs(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.abs)
|
||||
self.assertRaises(TypeError, operator.abs, None)
|
||||
self.assertEqual(operator.abs(-1), 1)
|
||||
self.assertEqual(operator.abs(1), 1)
|
||||
|
||||
def test_add(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.add)
|
||||
self.assertRaises(TypeError, operator.add, None, None)
|
||||
self.assertTrue(operator.add(3, 4) == 7)
|
||||
|
||||
def test_bitwise_and(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.and_)
|
||||
self.assertRaises(TypeError, operator.and_, None, None)
|
||||
self.assertTrue(operator.and_(0xf, 0xa) == 0xa)
|
||||
|
||||
def test_concat(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.concat)
|
||||
self.assertRaises(TypeError, operator.concat, None, None)
|
||||
self.assertTrue(operator.concat('py', 'thon') == 'python')
|
||||
|
@ -125,12 +137,14 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertRaises(TypeError, operator.concat, 13, 29)
|
||||
|
||||
def test_countOf(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.countOf)
|
||||
self.assertRaises(TypeError, operator.countOf, None, None)
|
||||
self.assertTrue(operator.countOf([1, 2, 1, 3, 1, 4], 3) == 1)
|
||||
self.assertTrue(operator.countOf([1, 2, 1, 3, 1, 4], 5) == 0)
|
||||
|
||||
def test_delitem(self):
|
||||
operator = self.module
|
||||
a = [4, 3, 2, 1]
|
||||
self.assertRaises(TypeError, operator.delitem, a)
|
||||
self.assertRaises(TypeError, operator.delitem, a, None)
|
||||
|
@ -138,33 +152,39 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertTrue(a == [4, 2, 1])
|
||||
|
||||
def test_floordiv(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.floordiv, 5)
|
||||
self.assertRaises(TypeError, operator.floordiv, None, None)
|
||||
self.assertTrue(operator.floordiv(5, 2) == 2)
|
||||
|
||||
def test_truediv(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.truediv, 5)
|
||||
self.assertRaises(TypeError, operator.truediv, None, None)
|
||||
self.assertTrue(operator.truediv(5, 2) == 2.5)
|
||||
|
||||
def test_getitem(self):
|
||||
operator = self.module
|
||||
a = range(10)
|
||||
self.assertRaises(TypeError, operator.getitem)
|
||||
self.assertRaises(TypeError, operator.getitem, a, None)
|
||||
self.assertTrue(operator.getitem(a, 2) == 2)
|
||||
|
||||
def test_indexOf(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.indexOf)
|
||||
self.assertRaises(TypeError, operator.indexOf, None, None)
|
||||
self.assertTrue(operator.indexOf([4, 3, 2, 1], 3) == 1)
|
||||
self.assertRaises(ValueError, operator.indexOf, [4, 3, 2, 1], 0)
|
||||
|
||||
def test_invert(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.invert)
|
||||
self.assertRaises(TypeError, operator.invert, None)
|
||||
self.assertEqual(operator.inv(4), -5)
|
||||
|
||||
def test_lshift(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.lshift)
|
||||
self.assertRaises(TypeError, operator.lshift, None, 42)
|
||||
self.assertTrue(operator.lshift(5, 1) == 10)
|
||||
|
@ -172,16 +192,19 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertRaises(ValueError, operator.lshift, 2, -1)
|
||||
|
||||
def test_mod(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.mod)
|
||||
self.assertRaises(TypeError, operator.mod, None, 42)
|
||||
self.assertTrue(operator.mod(5, 2) == 1)
|
||||
|
||||
def test_mul(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.mul)
|
||||
self.assertRaises(TypeError, operator.mul, None, None)
|
||||
self.assertTrue(operator.mul(5, 2) == 10)
|
||||
|
||||
def test_neg(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.neg)
|
||||
self.assertRaises(TypeError, operator.neg, None)
|
||||
self.assertEqual(operator.neg(5), -5)
|
||||
|
@ -190,11 +213,13 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertEqual(operator.neg(-0), 0)
|
||||
|
||||
def test_bitwise_or(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.or_)
|
||||
self.assertRaises(TypeError, operator.or_, None, None)
|
||||
self.assertTrue(operator.or_(0xa, 0x5) == 0xf)
|
||||
|
||||
def test_pos(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.pos)
|
||||
self.assertRaises(TypeError, operator.pos, None)
|
||||
self.assertEqual(operator.pos(5), 5)
|
||||
|
@ -203,14 +228,15 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertEqual(operator.pos(-0), 0)
|
||||
|
||||
def test_pow(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.pow)
|
||||
self.assertRaises(TypeError, operator.pow, None, None)
|
||||
self.assertEqual(operator.pow(3,5), 3**5)
|
||||
self.assertEqual(operator.__pow__(3,5), 3**5)
|
||||
self.assertRaises(TypeError, operator.pow, 1)
|
||||
self.assertRaises(TypeError, operator.pow, 1, 2, 3)
|
||||
|
||||
def test_rshift(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.rshift)
|
||||
self.assertRaises(TypeError, operator.rshift, None, 42)
|
||||
self.assertTrue(operator.rshift(5, 1) == 2)
|
||||
|
@ -218,12 +244,14 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertRaises(ValueError, operator.rshift, 2, -1)
|
||||
|
||||
def test_contains(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.contains)
|
||||
self.assertRaises(TypeError, operator.contains, None, None)
|
||||
self.assertTrue(operator.contains(range(4), 2))
|
||||
self.assertFalse(operator.contains(range(4), 5))
|
||||
|
||||
def test_setitem(self):
|
||||
operator = self.module
|
||||
a = list(range(3))
|
||||
self.assertRaises(TypeError, operator.setitem, a)
|
||||
self.assertRaises(TypeError, operator.setitem, a, None, None)
|
||||
|
@ -232,11 +260,13 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertRaises(IndexError, operator.setitem, a, 4, 2)
|
||||
|
||||
def test_sub(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.sub)
|
||||
self.assertRaises(TypeError, operator.sub, None, None)
|
||||
self.assertTrue(operator.sub(5, 2) == 3)
|
||||
|
||||
def test_truth(self):
|
||||
operator = self.module
|
||||
class C(object):
|
||||
def __bool__(self):
|
||||
raise SyntaxError
|
||||
|
@ -248,11 +278,13 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertFalse(operator.truth([]))
|
||||
|
||||
def test_bitwise_xor(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.xor)
|
||||
self.assertRaises(TypeError, operator.xor, None, None)
|
||||
self.assertTrue(operator.xor(0xb, 0xc) == 0x7)
|
||||
|
||||
def test_is(self):
|
||||
operator = self.module
|
||||
a = b = 'xyzpdq'
|
||||
c = a[:3] + b[3:]
|
||||
self.assertRaises(TypeError, operator.is_)
|
||||
|
@ -260,6 +292,7 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertFalse(operator.is_(a,c))
|
||||
|
||||
def test_is_not(self):
|
||||
operator = self.module
|
||||
a = b = 'xyzpdq'
|
||||
c = a[:3] + b[3:]
|
||||
self.assertRaises(TypeError, operator.is_not)
|
||||
|
@ -267,6 +300,7 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertTrue(operator.is_not(a,c))
|
||||
|
||||
def test_attrgetter(self):
|
||||
operator = self.module
|
||||
class A:
|
||||
pass
|
||||
a = A()
|
||||
|
@ -316,6 +350,7 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertEqual(f(a), ('arthur', 'thomas', 'johnson'))
|
||||
|
||||
def test_itemgetter(self):
|
||||
operator = self.module
|
||||
a = 'ABCDE'
|
||||
f = operator.itemgetter(2)
|
||||
self.assertEqual(f(a), 'C')
|
||||
|
@ -350,12 +385,15 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertRaises(TypeError, operator.itemgetter(2, 'x', 5), data)
|
||||
|
||||
def test_methodcaller(self):
|
||||
operator = self.module
|
||||
self.assertRaises(TypeError, operator.methodcaller)
|
||||
class A:
|
||||
def foo(self, *args, **kwds):
|
||||
return args[0] + args[1]
|
||||
def bar(self, f=42):
|
||||
return f
|
||||
def baz(*args, **kwds):
|
||||
return kwds['name'], kwds['self']
|
||||
a = A()
|
||||
f = operator.methodcaller('foo')
|
||||
self.assertRaises(IndexError, f, a)
|
||||
|
@ -366,8 +404,11 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertRaises(TypeError, f, a, a)
|
||||
f = operator.methodcaller('bar', f=5)
|
||||
self.assertEqual(f(a), 5)
|
||||
f = operator.methodcaller('baz', name='spam', self='eggs')
|
||||
self.assertEqual(f(a), ('spam', 'eggs'))
|
||||
|
||||
def test_inplace(self):
|
||||
operator = self.module
|
||||
class C(object):
|
||||
def __iadd__ (self, other): return "iadd"
|
||||
def __iand__ (self, other): return "iand"
|
||||
|
@ -396,21 +437,9 @@ class OperatorTestCase(unittest.TestCase):
|
|||
self.assertEqual(operator.itruediv (c, 5), "itruediv")
|
||||
self.assertEqual(operator.ixor (c, 5), "ixor")
|
||||
self.assertEqual(operator.iconcat (c, c), "iadd")
|
||||
self.assertEqual(operator.__iadd__ (c, 5), "iadd")
|
||||
self.assertEqual(operator.__iand__ (c, 5), "iand")
|
||||
self.assertEqual(operator.__ifloordiv__(c, 5), "ifloordiv")
|
||||
self.assertEqual(operator.__ilshift__ (c, 5), "ilshift")
|
||||
self.assertEqual(operator.__imod__ (c, 5), "imod")
|
||||
self.assertEqual(operator.__imul__ (c, 5), "imul")
|
||||
self.assertEqual(operator.__ior__ (c, 5), "ior")
|
||||
self.assertEqual(operator.__ipow__ (c, 5), "ipow")
|
||||
self.assertEqual(operator.__irshift__ (c, 5), "irshift")
|
||||
self.assertEqual(operator.__isub__ (c, 5), "isub")
|
||||
self.assertEqual(operator.__itruediv__ (c, 5), "itruediv")
|
||||
self.assertEqual(operator.__ixor__ (c, 5), "ixor")
|
||||
self.assertEqual(operator.__iconcat__ (c, c), "iadd")
|
||||
|
||||
def test_length_hint(self):
|
||||
operator = self.module
|
||||
class X(object):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
@ -434,24 +463,22 @@ class OperatorTestCase(unittest.TestCase):
|
|||
with self.assertRaises(LookupError):
|
||||
operator.length_hint(X(LookupError))
|
||||
|
||||
def test_dunder_is_original(self):
|
||||
operator = self.module
|
||||
|
||||
def test_main(verbose=None):
|
||||
import sys
|
||||
test_classes = (
|
||||
OperatorTestCase,
|
||||
)
|
||||
names = [name for name in dir(operator) if not name.startswith('_')]
|
||||
for name in names:
|
||||
orig = getattr(operator, name)
|
||||
dunder = getattr(operator, '__' + name.strip('_') + '__', None)
|
||||
if dunder:
|
||||
self.assertIs(dunder, orig)
|
||||
|
||||
support.run_unittest(*test_classes)
|
||||
class PyOperatorTestCase(OperatorTestCase, unittest.TestCase):
|
||||
module = py_operator
|
||||
|
||||
# verify reference counting
|
||||
if verbose and hasattr(sys, "gettotalrefcount"):
|
||||
import gc
|
||||
counts = [None] * 5
|
||||
for i in range(len(counts)):
|
||||
support.run_unittest(*test_classes)
|
||||
gc.collect()
|
||||
counts[i] = sys.gettotalrefcount()
|
||||
print(counts)
|
||||
@unittest.skipUnless(c_operator, 'requires _operator')
|
||||
class COperatorTestCase(OperatorTestCase, unittest.TestCase):
|
||||
module = c_operator
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_main(verbose=True)
|
||||
unittest.main()
|
||||
|
|
|
@ -49,6 +49,9 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #16694: Add a pure Python implementation of the operator module.
|
||||
Patch by Zachary Ware.
|
||||
|
||||
- Issue #11182: remove the unused and undocumented pydoc.Scanner class.
|
||||
Patch by Martin Morrison.
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ _sre _sre.c # Fredrik Lundh's new regular expressions
|
|||
_codecs _codecsmodule.c # access to the builtin codecs and codec registry
|
||||
_weakref _weakref.c # weak references
|
||||
_functools _functoolsmodule.c # Tools for working with functions and callable objects
|
||||
operator operator.c # operator.add() and similar goodies
|
||||
_operator _operator.c # operator.add() and similar goodies
|
||||
_collections _collectionsmodule.c # Container types
|
||||
itertools itertoolsmodule.c # Functions creating iterators for efficient looping
|
||||
|
||||
|
|
|
@ -322,17 +322,15 @@ compare_digest(PyObject *self, PyObject *args)
|
|||
/* operator methods **********************************************************/
|
||||
|
||||
#define spam1(OP,DOC) {#OP, OP, METH_VARARGS, PyDoc_STR(DOC)},
|
||||
#define spam2(OP,ALTOP,DOC) {#OP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)}, \
|
||||
{#ALTOP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)},
|
||||
#define spam2(OP,DOC) {#OP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)},
|
||||
#define spam1o(OP,DOC) {#OP, OP, METH_O, PyDoc_STR(DOC)},
|
||||
#define spam2o(OP,ALTOP,DOC) {#OP, op_##OP, METH_O, PyDoc_STR(DOC)}, \
|
||||
{#ALTOP, op_##OP, METH_O, PyDoc_STR(DOC)},
|
||||
#define spam2o(OP,DOC) {#OP, op_##OP, METH_O, PyDoc_STR(DOC)},
|
||||
|
||||
static struct PyMethodDef operator_methods[] = {
|
||||
|
||||
spam1o(truth,
|
||||
"truth(a) -- Return True if a is true, False otherwise.")
|
||||
spam2(contains,__contains__,
|
||||
spam2(contains,
|
||||
"contains(a, b) -- Same as b in a (note reversed operands).")
|
||||
spam1(indexOf,
|
||||
"indexOf(a, b) -- Return the first index of b in a.")
|
||||
|
@ -341,53 +339,53 @@ spam1(countOf,
|
|||
|
||||
spam1(is_, "is_(a, b) -- Same as a is b.")
|
||||
spam1(is_not, "is_not(a, b) -- Same as a is not b.")
|
||||
spam2o(index, __index__, "index(a) -- Same as a.__index__()")
|
||||
spam2(add,__add__, "add(a, b) -- Same as a + b.")
|
||||
spam2(sub,__sub__, "sub(a, b) -- Same as a - b.")
|
||||
spam2(mul,__mul__, "mul(a, b) -- Same as a * b.")
|
||||
spam2(floordiv,__floordiv__, "floordiv(a, b) -- Same as a // b.")
|
||||
spam2(truediv,__truediv__, "truediv(a, b) -- Same as a / b.")
|
||||
spam2(mod,__mod__, "mod(a, b) -- Same as a % b.")
|
||||
spam2o(neg,__neg__, "neg(a) -- Same as -a.")
|
||||
spam2o(pos,__pos__, "pos(a) -- Same as +a.")
|
||||
spam2o(abs,__abs__, "abs(a) -- Same as abs(a).")
|
||||
spam2o(inv,__inv__, "inv(a) -- Same as ~a.")
|
||||
spam2o(invert,__invert__, "invert(a) -- Same as ~a.")
|
||||
spam2(lshift,__lshift__, "lshift(a, b) -- Same as a << b.")
|
||||
spam2(rshift,__rshift__, "rshift(a, b) -- Same as a >> b.")
|
||||
spam2o(not_,__not__, "not_(a) -- Same as not a.")
|
||||
spam2(and_,__and__, "and_(a, b) -- Same as a & b.")
|
||||
spam2(xor,__xor__, "xor(a, b) -- Same as a ^ b.")
|
||||
spam2(or_,__or__, "or_(a, b) -- Same as a | b.")
|
||||
spam2(iadd,__iadd__, "a = iadd(a, b) -- Same as a += b.")
|
||||
spam2(isub,__isub__, "a = isub(a, b) -- Same as a -= b.")
|
||||
spam2(imul,__imul__, "a = imul(a, b) -- Same as a *= b.")
|
||||
spam2(ifloordiv,__ifloordiv__, "a = ifloordiv(a, b) -- Same as a //= b.")
|
||||
spam2(itruediv,__itruediv__, "a = itruediv(a, b) -- Same as a /= b")
|
||||
spam2(imod,__imod__, "a = imod(a, b) -- Same as a %= b.")
|
||||
spam2(ilshift,__ilshift__, "a = ilshift(a, b) -- Same as a <<= b.")
|
||||
spam2(irshift,__irshift__, "a = irshift(a, b) -- Same as a >>= b.")
|
||||
spam2(iand,__iand__, "a = iand(a, b) -- Same as a &= b.")
|
||||
spam2(ixor,__ixor__, "a = ixor(a, b) -- Same as a ^= b.")
|
||||
spam2(ior,__ior__, "a = ior(a, b) -- Same as a |= b.")
|
||||
spam2(concat,__concat__,
|
||||
spam2o(index, "index(a) -- Same as a.__index__()")
|
||||
spam2(add, "add(a, b) -- Same as a + b.")
|
||||
spam2(sub, "sub(a, b) -- Same as a - b.")
|
||||
spam2(mul, "mul(a, b) -- Same as a * b.")
|
||||
spam2(floordiv, "floordiv(a, b) -- Same as a // b.")
|
||||
spam2(truediv, "truediv(a, b) -- Same as a / b.")
|
||||
spam2(mod, "mod(a, b) -- Same as a % b.")
|
||||
spam2o(neg, "neg(a) -- Same as -a.")
|
||||
spam2o(pos, "pos(a) -- Same as +a.")
|
||||
spam2o(abs, "abs(a) -- Same as abs(a).")
|
||||
spam2o(inv, "inv(a) -- Same as ~a.")
|
||||
spam2o(invert, "invert(a) -- Same as ~a.")
|
||||
spam2(lshift, "lshift(a, b) -- Same as a << b.")
|
||||
spam2(rshift, "rshift(a, b) -- Same as a >> b.")
|
||||
spam2o(not_, "not_(a) -- Same as not a.")
|
||||
spam2(and_, "and_(a, b) -- Same as a & b.")
|
||||
spam2(xor, "xor(a, b) -- Same as a ^ b.")
|
||||
spam2(or_, "or_(a, b) -- Same as a | b.")
|
||||
spam2(iadd, "a = iadd(a, b) -- Same as a += b.")
|
||||
spam2(isub, "a = isub(a, b) -- Same as a -= b.")
|
||||
spam2(imul, "a = imul(a, b) -- Same as a *= b.")
|
||||
spam2(ifloordiv, "a = ifloordiv(a, b) -- Same as a //= b.")
|
||||
spam2(itruediv, "a = itruediv(a, b) -- Same as a /= b")
|
||||
spam2(imod, "a = imod(a, b) -- Same as a %= b.")
|
||||
spam2(ilshift, "a = ilshift(a, b) -- Same as a <<= b.")
|
||||
spam2(irshift, "a = irshift(a, b) -- Same as a >>= b.")
|
||||
spam2(iand, "a = iand(a, b) -- Same as a &= b.")
|
||||
spam2(ixor, "a = ixor(a, b) -- Same as a ^= b.")
|
||||
spam2(ior, "a = ior(a, b) -- Same as a |= b.")
|
||||
spam2(concat,
|
||||
"concat(a, b) -- Same as a + b, for a and b sequences.")
|
||||
spam2(iconcat,__iconcat__,
|
||||
spam2(iconcat,
|
||||
"a = iconcat(a, b) -- Same as a += b, for a and b sequences.")
|
||||
spam2(getitem,__getitem__,
|
||||
spam2(getitem,
|
||||
"getitem(a, b) -- Same as a[b].")
|
||||
spam2(setitem,__setitem__,
|
||||
spam2(setitem,
|
||||
"setitem(a, b, c) -- Same as a[b] = c.")
|
||||
spam2(delitem,__delitem__,
|
||||
spam2(delitem,
|
||||
"delitem(a, b) -- Same as del a[b].")
|
||||
spam2(pow,__pow__, "pow(a, b) -- Same as a ** b.")
|
||||
spam2(ipow,__ipow__, "a = ipow(a, b) -- Same as a **= b.")
|
||||
spam2(lt,__lt__, "lt(a, b) -- Same as a<b.")
|
||||
spam2(le,__le__, "le(a, b) -- Same as a<=b.")
|
||||
spam2(eq,__eq__, "eq(a, b) -- Same as a==b.")
|
||||
spam2(ne,__ne__, "ne(a, b) -- Same as a!=b.")
|
||||
spam2(gt,__gt__, "gt(a, b) -- Same as a>b.")
|
||||
spam2(ge,__ge__, "ge(a, b) -- Same as a>=b.")
|
||||
spam2(pow, "pow(a, b) -- Same as a ** b.")
|
||||
spam2(ipow, "a = ipow(a, b) -- Same as a **= b.")
|
||||
spam2(lt, "lt(a, b) -- Same as a<b.")
|
||||
spam2(le, "le(a, b) -- Same as a<=b.")
|
||||
spam2(eq, "eq(a, b) -- Same as a==b.")
|
||||
spam2(ne, "ne(a, b) -- Same as a!=b.")
|
||||
spam2(gt, "gt(a, b) -- Same as a>b.")
|
||||
spam2(ge, "ge(a, b) -- Same as a>=b.")
|
||||
|
||||
{"_compare_digest", (PyCFunction)compare_digest, METH_VARARGS,
|
||||
compare_digest__doc__},
|
||||
|
@ -487,8 +485,8 @@ PyDoc_STRVAR(itemgetter_doc,
|
|||
"itemgetter(item, ...) --> itemgetter object\n\
|
||||
\n\
|
||||
Return a callable object that fetches the given item(s) from its operand.\n\
|
||||
After, f=itemgetter(2), the call f(r) returns r[2].\n\
|
||||
After, g=itemgetter(2,5,3), the call g(r) returns (r[2], r[5], r[3])");
|
||||
After f=itemgetter(2), the call f(r) returns r[2].\n\
|
||||
After g=itemgetter(2,5,3), the call g(r) returns (r[2], r[5], r[3])");
|
||||
|
||||
static PyTypeObject itemgetter_type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
|
@ -739,9 +737,9 @@ PyDoc_STRVAR(attrgetter_doc,
|
|||
"attrgetter(attr, ...) --> attrgetter object\n\
|
||||
\n\
|
||||
Return a callable object that fetches the given attribute(s) from its operand.\n\
|
||||
After, f=attrgetter('name'), the call f(r) returns r.name.\n\
|
||||
After, g=attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\
|
||||
After, h=attrgetter('name.first', 'name.last'), the call h(r) returns\n\
|
||||
After f=attrgetter('name'), the call f(r) returns r.name.\n\
|
||||
After g=attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\
|
||||
After h=attrgetter('name.first', 'name.last'), the call h(r) returns\n\
|
||||
(r.name.first, r.name.last).");
|
||||
|
||||
static PyTypeObject attrgetter_type = {
|
||||
|
@ -871,8 +869,8 @@ PyDoc_STRVAR(methodcaller_doc,
|
|||
"methodcaller(name, ...) --> methodcaller object\n\
|
||||
\n\
|
||||
Return a callable object that calls the given method on its operand.\n\
|
||||
After, f = methodcaller('name'), the call f(r) returns r.name().\n\
|
||||
After, g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\
|
||||
After f = methodcaller('name'), the call f(r) returns r.name().\n\
|
||||
After g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\
|
||||
r.name('date', foo=1).");
|
||||
|
||||
static PyTypeObject methodcaller_type = {
|
||||
|
@ -919,12 +917,12 @@ static PyTypeObject methodcaller_type = {
|
|||
};
|
||||
|
||||
|
||||
/* Initialization function for the module (*must* be called PyInit_operator) */
|
||||
/* Initialization function for the module (*must* be called PyInit__operator) */
|
||||
|
||||
|
||||
static struct PyModuleDef operatormodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"operator",
|
||||
"_operator",
|
||||
operator_doc,
|
||||
-1,
|
||||
operator_methods,
|
||||
|
@ -935,7 +933,7 @@ static struct PyModuleDef operatormodule = {
|
|||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit_operator(void)
|
||||
PyInit__operator(void)
|
||||
{
|
||||
PyObject *m;
|
||||
|
|
@ -1119,7 +1119,7 @@
|
|||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\Modules\operator.c"
|
||||
RelativePath="..\..\Modules\_operator.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
|
|
|
@ -17,7 +17,7 @@ extern PyObject* PyInit_gc(void);
|
|||
extern PyObject* PyInit_math(void);
|
||||
extern PyObject* PyInit__md5(void);
|
||||
extern PyObject* PyInit_nt(void);
|
||||
extern PyObject* PyInit_operator(void);
|
||||
extern PyObject* PyInit__operator(void);
|
||||
extern PyObject* PyInit_signal(void);
|
||||
extern PyObject* PyInit__sha1(void);
|
||||
extern PyObject* PyInit__sha256(void);
|
||||
|
@ -87,7 +87,7 @@ struct _inittab _PyImport_Inittab[] = {
|
|||
{"gc", PyInit_gc},
|
||||
{"math", PyInit_math},
|
||||
{"nt", PyInit_nt}, /* Use the NT os functions, not posix */
|
||||
{"operator", PyInit_operator},
|
||||
{"_operator", PyInit__operator},
|
||||
{"signal", PyInit_signal},
|
||||
{"_md5", PyInit__md5},
|
||||
{"_sha1", PyInit__sha1},
|
||||
|
|
|
@ -517,7 +517,7 @@
|
|||
<ClCompile Include="..\Modules\mathmodule.c" />
|
||||
<ClCompile Include="..\Modules\md5module.c" />
|
||||
<ClCompile Include="..\Modules\mmapmodule.c" />
|
||||
<ClCompile Include="..\Modules\operator.c" />
|
||||
<ClCompile Include="..\Modules\_operator.c" />
|
||||
<ClCompile Include="..\Modules\parsermodule.c" />
|
||||
<ClCompile Include="..\Modules\posixmodule.c" />
|
||||
<ClCompile Include="..\Modules\rotatingtree.c" />
|
||||
|
|
|
@ -501,7 +501,7 @@
|
|||
<ClCompile Include="..\Modules\mmapmodule.c">
|
||||
<Filter>Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Modules\operator.c">
|
||||
<ClCompile Include="..\Modules\_operator.c">
|
||||
<Filter>Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Modules\parsermodule.c">
|
||||
|
|
Loading…
Reference in New Issue