Author: Amaury Forgeot d'Arc <amaur...@gmail.com>
Branch: py3.6
Changeset: r93461:77d216c5b248
Date: 2017-12-17 22:03 +0100
http://bitbucket.org/pypy/pypy/changeset/77d216c5b248/

Log:    CPython Issue #28727: re.Pattern objects created by re.compile()
        become comparable (only x==y and x!=y operators)

diff --git a/pypy/module/_sre/interp_sre.py b/pypy/module/_sre/interp_sre.py
--- a/pypy/module/_sre/interp_sre.py
+++ b/pypy/module/_sre/interp_sre.py
@@ -5,6 +5,7 @@
 from pypy.interpreter.typedef import make_weakref_descr
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.interpreter.error import OperationError, oefmt
+from rpython.rlib.objectmodel import compute_hash
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib import jit
 from rpython.rlib.rstring import StringBuilder, UnicodeBuilder
@@ -133,6 +134,24 @@
             uflags = u'|'.join([item.decode('latin-1') for item in flag_items])
         return space.newunicode(u're.compile(%s%s%s)' % (u, usep, uflags))
 
+    def descr_eq(self, space, w_other):
+        if not isinstance(w_other, W_SRE_Pattern):
+            return space.w_NotImplemented
+        other = w_other
+        # Compare the code and the pattern because the same pattern can
+        # produce different codes depending on the locale used to compile the
+        # pattern when the re.LOCALE flag is used. Don't compare groups,
+        # indexgroup nor groupindex: they are derivated from the pattern.
+        return space.newbool(
+            self.flags == other.flags and
+            self.code == other.code and
+            space.eq_w(self.w_pattern, other.w_pattern))
+
+    def descr_hash(self, space):
+        code = ''.join([chr(c) for c in self.code])
+        return space.newint(compute_hash(
+            (self.flags, code, space.hash_w(self.w_pattern))))
+
     def fget_groupindex(self, space):
         w_groupindex = self.w_groupindex
         if space.isinstance_w(w_groupindex, space.w_dict):
@@ -488,6 +507,8 @@
     __deepcopy__ = interp2app(W_SRE_Pattern.cannot_copy_w),
     __repr__     = interp2app(W_SRE_Pattern.repr_w),
     __weakref__  = make_weakref_descr(W_SRE_Pattern),
+    __eq__       = interp2app(W_SRE_Pattern.descr_eq),
+    __hash__     = interp2app(W_SRE_Pattern.descr_hash),
     findall      = interp2app(W_SRE_Pattern.findall_w),
     finditer     = interp2app(W_SRE_Pattern.finditer_w),
     match        = interp2app(W_SRE_Pattern.match_w),
diff --git a/pypy/module/_sre/test/test_app_sre.py 
b/pypy/module/_sre/test/test_app_sre.py
--- a/pypy/module/_sre/test/test_app_sre.py
+++ b/pypy/module/_sre/test/test_app_sre.py
@@ -133,6 +133,33 @@
         assert repr(r) == (
             r"""re.compile('f(o"\\d)', re.IGNORECASE|re.DOTALL|re.VERBOSE)""")
 
+    def test_pattern_compare(self):
+        import re
+        pattern1 = re.compile('abc', re.IGNORECASE)
+
+        # equal to itself
+        assert pattern1 == pattern1
+        assert not(pattern1 != pattern1)
+        # equal
+        re.purge()
+        pattern2 = re.compile('abc', re.IGNORECASE)
+        assert hash(pattern2) == hash(pattern1)
+        assert pattern2 == pattern1
+
+        # not equal: different pattern
+        re.purge()
+        pattern3 = re.compile('XYZ', re.IGNORECASE)
+        # warranty that hash values are different
+        assert pattern3 != pattern1
+
+        # not equal: different flag (flags=0)
+        re.purge()
+        pattern4 = re.compile('abc')
+        assert pattern4 != pattern1
+
+        # only == and != comparison operators are supported
+        raises(TypeError, "pattern1 < pattern2")
+
 
 class AppTestSreMatch:
     spaceconfig = dict(usemodules=('array', ))
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to