[pypy-commit] pypy stdlib-2.7.8: Initial implementation of operator._compare_digest

alex_gaynor noreply at buildbot.pypy.org
Thu Aug 21 03:19:33 CEST 2014


Author: Alex Gaynor <alex.gaynor at 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)))
+
+
+ at 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)


More information about the pypy-commit mailing list