[pypy-commit] pypy default: Issue #2758

arigo pypy.commits at gmail.com
Sat Feb 24 12:00:12 EST 2018


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r93883:89245c285fa0
Date: 2018-02-24 17:59 +0100
http://bitbucket.org/pypy/pypy/changeset/89245c285fa0/

Log:	Issue #2758

	Test and fix for re.sub(callback) receiving an immutable match
	object

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
@@ -303,8 +303,11 @@
             if not (last_pos == ctx.match_start
                              == ctx.match_end and n > 0):
                 # the above ignores empty matches on latest position
+                last_pos = ctx.match_end
                 if filter_is_callable:
                     w_match = self.getmatch(ctx, True)
+                    # make a copy of 'ctx'; see test_sub_matches_stay_valid
+                    ctx = ctx.fresh_copy(start) # match_start/match_end dropped
                     w_piece = space.call_function(w_filter, w_match)
                     if not space.is_w(w_piece, space.w_None):
                         assert strbuilder is None and unicodebuilder is None
@@ -321,7 +324,6 @@
                             unicodebuilder.append(filter_as_unicode)
                     else:
                         sublist_w.append(w_filter)
-                last_pos = ctx.match_end
                 n += 1
             elif last_pos >= ctx.end:
                 break    # empty match at the end: finished
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
@@ -328,6 +328,18 @@
         KEYCRE = re.compile(r"%\(([^)]*)\)s|.")
         raises(TypeError, KEYCRE.sub, "hello", {"%(": 1})
 
+    def test_sub_matches_stay_valid(self):
+        import re
+        matches = []
+        def callback(match):
+            matches.append(match)
+            return "x"
+        result = re.compile(r"[ab]").sub(callback, "acb")
+        assert result == "xcx"
+        assert len(matches) == 2
+        assert matches[0].group() == "a"
+        assert matches[1].group() == "b"
+
 
 class AppTestSreScanner:
     def test_scanner_attributes(self):


More information about the pypy-commit mailing list