XZise has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/231899

Change subject: [FEAT] replaceExcept: Support custom parameters
......................................................................

[FEAT] replaceExcept: Support custom parameters

This adds the ability to support custom parameters when the replacement is a
callable. This can be used to pass the page to the callable in the replace
script.

Bug: T109220
Change-Id: Iee52388d8a137a21252476cb7926e4705e0324fa
---
M pywikibot/textlib.py
M scripts/replace.py
M tests/textlib_tests.py
3 files changed, 65 insertions(+), 11 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/pywikibot/core 
refs/changes/99/231899/1

diff --git a/pywikibot/textlib.py b/pywikibot/textlib.py
index 77454fc..bf10b7a 100644
--- a/pywikibot/textlib.py
+++ b/pywikibot/textlib.py
@@ -225,7 +225,8 @@
 
 
 def replaceExcept(text, old, new, exceptions, caseInsensitive=False,
-                  allowoverlap=False, marker='', site=None):
+                  allowoverlap=False, marker='', site=None,
+                  replacement_parameters=None):
     """
     Return text with 'old' replaced by 'new', ignoring specified types of text.
 
@@ -245,8 +246,17 @@
     @type caseInsensitive: bool
     @param marker: a string that will be added to the last replacement;
         if nothing is changed, it is added at the end
-
+    @param replacement_parameters: if C{new} is a callable these parameters
+        are forwarded additionally to the match.
+    @type replacement_parameters: dict or None
     """
+    if replacement_parameters:
+        if not callable(new):
+            raise ValueError('The replacement_parameters cannot be set when '
+                             'the replacement is not callable.')
+    else:
+        replacement_parameters = {}
+
     # if we got a string, compile it as a regular expression
     if isinstance(old, basestring):
         if caseInsensitive:
@@ -289,7 +299,7 @@
             if callable(new):
                 # the parameter new can be a function which takes the match
                 # as a parameter.
-                replacement = new(match)
+                replacement = new(match, **replacement_parameters)
             else:
                 # it is not a function, but a string.
 
diff --git a/scripts/replace.py b/scripts/replace.py
index 9bcfeb1..981d580 100755
--- a/scripts/replace.py
+++ b/scripts/replace.py
@@ -179,12 +179,14 @@
 
     """The replacement instructions."""
 
-    def __init__(self, old, new, edit_summary=None, default_summary=True):
+    def __init__(self, old, new, edit_summary=None, default_summary=True,
+                 page_parameter=False):
         self.old = old
         self.old_regex = None
         self.new = new
         self._edit_summary = edit_summary
         self.default_summary = default_summary
+        self.page_parameter = page_parameter
 
     @property
     def edit_summary(self):
@@ -287,7 +289,7 @@
     """
 
     def __init__(self, use_regex, exceptions, case_insensitive, edit_summary,
-                 name):
+                 name, page_parameter=False):
         super(ReplacementList, self).__init__()
         self.use_regex = use_regex
         self._exceptions = exceptions
@@ -295,6 +297,7 @@
         self.case_insensitive = case_insensitive
         self.edit_summary = edit_summary
         self.name = name
+        self.page_parameter = page_parameter
 
     def _compile_exceptions(self, use_regex, flags):
         if not self.exceptions and self._exceptions is not None:
@@ -343,6 +346,11 @@
         Container objects must have a "name" attribute.
         """
         return self.fix_set
+
+    @property
+    def page_parameter(self):
+        """Return the page_parameter of the container."""
+        return self.container.page_parameter
 
     def _compile(self, use_regex, flags):
         super(ReplacementListEntry, self)._compile(use_regex, flags)
@@ -589,10 +597,15 @@
                             replacement.description, page.title(asLink=True)))
                 continue
             old_text = new_text
+            if replacement.page_parameter:
+                parameters = {'page': page}
+            else:
+                parameters = {}
             new_text = textlib.replaceExcept(
                 new_text, replacement.old_regex, replacement.new,
                 exceptions + get_exceptions(replacement.exceptions or {}),
-                allowoverlap=self.allowoverlap, site=self.site)
+                allowoverlap=self.allowoverlap, site=self.site,
+                replacement_parameters=parameters)
             if old_text != new_text:
                 applied.add(replacement)
 
@@ -963,11 +976,9 @@
                 set_summary = i18n.translate(site, fix['msg'], fallback=True)
         else:
             set_summary = None
-        replacement_set = ReplacementList(fix.get('regex'),
-                                          fix.get('exceptions'),
-                                          fix.get('nocase'),
-                                          set_summary,
-                                          name=fix_name)
+        replacement_set = ReplacementList(
+            fix.get('regex'), fix.get('exceptions'), fix.get('nocase'),
+            set_summary, fix_name, fix.get('pass_page'))
         for replacement in fix['replacements']:
             summary = None if len(replacement) < 3 else replacement[2]
             if chars.contains_invisible(replacement[0]):
diff --git a/tests/textlib_tests.py b/tests/textlib_tests.py
index 1de1fa9..3248878 100644
--- a/tests/textlib_tests.py
+++ b/tests/textlib_tests.py
@@ -1027,6 +1027,39 @@
                                                r'X\g<foo>X', [], 
site=self.site),
                          r'X\g<bar>X')
 
+    def test_callable_replacement(self):
+        """Test replaceExcept with the replacement being callable."""
+        def no_parameters(match):
+            return 'np'
+
+        def req_parameter(match, value):
+            return value
+
+        def opt_parameter(match, value='nv'):
+            return value
+
+        self.assertEqual(textlib.replaceExcept('barfoo', 'foo', no_parameters,
+                                               [], site=self.site),
+                         'barnp')
+        self.assertRaises(TypeError, textlib.replaceExcept,
+                          'barfoo', 'foo', no_parameters, [], site=self.site,
+                          replacement_parameters={'value': '42'})
+        self.assertRaises(TypeError, textlib.replaceExcept,
+                          'barfoo', 'foo', req_parameter, [], site=self.site)
+        self.assertEqual(
+            textlib.replaceExcept(
+                'barfoo', 'foo', req_parameter, [], site=self.site,
+                replacement_parameters={'value': '42'}),
+            'bar42')
+        self.assertEqual(textlib.replaceExcept('barfoo', 'foo', opt_parameter,
+                                               [], site=self.site),
+                         'barnv')
+        self.assertEqual(
+            textlib.replaceExcept(
+                'barfoo', 'foo', opt_parameter, [], site=self.site,
+                replacement_parameters={'value': '42'}),
+            'bar42')
+
 
 if __name__ == '__main__':
     try:

-- 
To view, visit https://gerrit.wikimedia.org/r/231899
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iee52388d8a137a21252476cb7926e4705e0324fa
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: XZise <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to