Author: Alex Gaynor <alex.gay...@gmail.com> Branch: stdlib-2.7.8 Changeset: r72945:6c4fc35d1793 Date: 2014-08-20 18:19 -0700 http://bitbucket.org/pypy/pypy/changeset/6c4fc35d1793/
Log: Initial implementation of operator._compare_digest diff --git a/pypy/module/operator/__init__.py b/pypy/module/operator/__init__.py --- a/pypy/module/operator/__init__.py +++ b/pypy/module/operator/__init__.py @@ -38,7 +38,9 @@ 'ilshift', 'imod', 'imul', 'ior', 'ipow', 'irepeat', 'irshift', 'isub', 'itruediv', 'ixor', '_length_hint'] - interpleveldefs = {} + interpleveldefs = { + '_compare_digest': 'interp_operator.compare_digest', + } for name in interp_names: interpleveldefs[name] = 'interp_operator.%s' % name diff --git a/pypy/module/operator/interp_operator.py b/pypy/module/operator/interp_operator.py --- a/pypy/module/operator/interp_operator.py +++ b/pypy/module/operator/interp_operator.py @@ -1,6 +1,9 @@ -from pypy.interpreter.error import OperationError +from rpython.rlib.objectmodel import specialize + +from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.gateway import unwrap_spec + def index(space, w_a): return space.index(w_a) @@ -70,7 +73,7 @@ def invert(space, w_obj,): 'invert(a) -- Same as ~a.' - return space.invert(w_obj) + return space.invert(w_obj) def isCallable(space, w_obj): 'isCallable(a) -- Same as callable(a).' @@ -96,7 +99,7 @@ def lshift(space, w_a, w_b): 'lshift(a, b) -- Same as a << b.' - return space.lshift(w_a, w_b) + return space.lshift(w_a, w_b) def lt(space, w_a, w_b): 'lt(a, b) -- Same as a<b.' @@ -112,7 +115,7 @@ def ne(space, w_a, w_b): 'ne(a, b) -- Same as a!=b.' - return space.ne(w_a, w_b) + return space.ne(w_a, w_b) def neg(space, w_obj,): 'neg(a) -- Same as -a.' @@ -128,7 +131,7 @@ def pos(space, w_obj,): 'pos(a) -- Same as +a.' - return space.pos(w_obj) + return space.pos(w_obj) def pow(space, w_a, w_b): 'pow(a, b) -- Same as a**b.' @@ -138,7 +141,7 @@ def rshift(space, w_a, w_b): 'rshift(a, b) -- Same as a >> b.' - return space.rshift(w_a, w_b) + return space.rshift(w_a, w_b) # sequenceIncludes @@ -150,7 +153,7 @@ def sub(space, w_a, w_b): 'sub(a, b) -- Same as a - b.' - return space.sub(w_a, w_b) + return space.sub(w_a, w_b) def truediv(space, w_a, w_b): 'truediv(a, b) -- Same as a / b when __future__.division is in effect.' @@ -184,7 +187,7 @@ def ilshift(space, w_a, w_b): 'ilshift(a, b) -- Same as a <<= b.' - return space.inplace_lshift(w_a, w_b) + return space.inplace_lshift(w_a, w_b) def imod(space, w_a, w_b): 'imod(a, b) -- Same as a %= b.' @@ -204,11 +207,11 @@ def irshift(space, w_a, w_b): 'irshift(a, b) -- Same as a >>= b.' - return space.inplace_rshift(w_a, w_b) + return space.inplace_rshift(w_a, w_b) def isub(space, w_a, w_b): 'isub(a, b) -- Same as a -= b.' - return space.inplace_sub(w_a, w_b) + return space.inplace_sub(w_a, w_b) def itruediv(space, w_a, w_b): 'itruediv(a, b) -- Same as a /= b when __future__.division is in effect.' @@ -246,3 +249,33 @@ @unwrap_spec(default=int) def _length_hint(space, w_iterable, default): return space.wrap(space.length_hint(w_iterable, default)) + +def compare_digest(space, w_a, w_b): + if ( + space.isinstance_w(w_a, space.w_unicode) and + space.isinstance_w(w_b, space.w_unicode) + ): + return space.wrap(tscmp(space.unicode_w(w_a), space.unicode_w(w_b))) + if ( + space.isinstance_w(w_a, space.w_unicode) or + space.isinstance_w(w_b, space.w_unicode) + ): + raise oefmt( + space.w_TypeError, + "unsupported operand types(s) or combination of types: '%N' and '%N'", + w_a, + w_b, + ) + else: + return space.wrap(tscmp(space.bufferstr_w(w_a), space.bufferstr_w(w_b))) + + +@specialize.argtype(0, 1) +def tscmp(a, b): + len_a = len(a) + len_b = len(b) + length = min(len(a), len(b)) + res = len_a ^ len_b + for i in xrange(length): + res |= ord(a[i]) ^ ord(b[i]) + return res == 0 diff --git a/pypy/module/operator/test/test_operator.py b/pypy/module/operator/test/test_operator.py --- a/pypy/module/operator/test/test_operator.py +++ b/pypy/module/operator/test/test_operator.py @@ -15,7 +15,7 @@ assert a.get3("foobar") == "b" assert a.getx(*(a,)) == 5 assert a.get3(obj="foobar") == "b" - + def test_getter_multiple_gest(self): import operator @@ -197,3 +197,110 @@ assert operator.__index__(42) == 42 exc = raises(TypeError, operator.index, "abc") assert str(exc.value) == "'str' object cannot be interpreted as an index" + + def test_compare_digest(self): + import operator + + # Testing input type exception handling + a, b = 100, 200 + raises(TypeError, operator._compare_digest, a, b) + a, b = 100, b"foobar" + raises(TypeError, operator._compare_digest, a, b) + a, b = b"foobar", 200 + raises(TypeError, operator._compare_digest, a, b) + a, b = u"foobar", b"foobar" + raises(TypeError, operator._compare_digest, a, b) + a, b = b"foobar", u"foobar" + raises(TypeError, operator._compare_digest, a, b) + + # Testing bytes of different lengths + a, b = b"foobar", b"foo" + assert not operator._compare_digest(a, b) + a, b = b"\xde\xad\xbe\xef", b"\xde\xad" + assert not operator._compare_digest(a, b) + + # Testing bytes of same lengths, different values + a, b = b"foobar", b"foobaz" + assert not operator._compare_digest(a, b) + a, b = b"\xde\xad\xbe\xef", b"\xab\xad\x1d\xea" + assert not operator._compare_digest(a, b) + + # Testing bytes of same lengths, same values + a, b = b"foobar", b"foobar" + assert operator._compare_digest(a, b) + a, b = b"\xde\xad\xbe\xef", b"\xde\xad\xbe\xef" + assert operator._compare_digest(a, b) + + # Testing bytearrays of same lengths, same values + a, b = bytearray(b"foobar"), bytearray(b"foobar") + assert operator._compare_digest(a, b) + + # Testing bytearrays of diffeent lengths + a, b = bytearray(b"foobar"), bytearray(b"foo") + assert not operator._compare_digest(a, b) + + # Testing bytearrays of same lengths, different values + a, b = bytearray(b"foobar"), bytearray(b"foobaz") + assert not operator._compare_digest(a, b) + + # Testing byte and bytearray of same lengths, same values + a, b = bytearray(b"foobar"), b"foobar" + assert operator._compare_digest(a, b) + assert operator._compare_digest(b, a) + + # Testing byte bytearray of diffeent lengths + a, b = bytearray(b"foobar"), b"foo" + assert not operator._compare_digest(a, b) + assert not operator._compare_digest(b, a) + + # Testing byte and bytearray of same lengths, different values + a, b = bytearray(b"foobar"), b"foobaz" + assert not operator._compare_digest(a, b) + assert not operator._compare_digest(b, a) + + # Testing str of same lengths + a, b = "foobar", "foobar" + assert operator._compare_digest(a, b) + + # Testing str of diffeent lengths + a, b = "foo", "foobar" + assert not operator._compare_digest(a, b) + + # Testing bytes of same lengths, different values + a, b = "foobar", "foobaz" + assert not operator._compare_digest(a, b) + + # Testing error cases + a, b = u"foobar", b"foobar" + raises(TypeError, operator._compare_digest, a, b) + a, b = b"foobar", u"foobar" + raises(TypeError, operator._compare_digest, a, b) + a, b = b"foobar", 1 + raises(TypeError, operator._compare_digest, a, b) + a, b = 100, 200 + raises(TypeError, operator._compare_digest, a, b) + a, b = "fooä", "fooä" + assert operator._compare_digest(a, b) + + # subclasses are supported by ignore __eq__ + class mystr(str): + def __eq__(self, other): + return False + + a, b = mystr("foobar"), mystr("foobar") + assert operator._compare_digest(a, b) + a, b = mystr("foobar"), "foobar" + assert operator._compare_digest(a, b) + a, b = mystr("foobar"), mystr("foobaz") + assert not operator._compare_digest(a, b) + + class mybytes(bytes): + def __eq__(self, other): + return False + + a, b = mybytes(b"foobar"), mybytes(b"foobar") + assert operator._compare_digest(a, b) + a, b = mybytes(b"foobar"), b"foobar" + assert operator._compare_digest(a, b) + a, b = mybytes(b"foobar"), mybytes(b"foobaz") + assert not operator._compare_digest(a, b) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit