jenkins-bot has submitted this change. ( 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1346042?usp=email )

Change subject: textlib: Support legacy encoded section titles
......................................................................

textlib: Support legacy encoded section titles

Match legacy anchors against encoded heading wikitext after checking plain
titles. Encoding headings preserves literal dot sequences alongside escaped
punctuation and UTF-8 characters. Reuse section parsing to retain equals
signs that belong to the heading.

Bug: T133276
Change-Id: I983df6f7b5606bb39587431554b87503808bb3e9
---
M pywikibot/textlib.py
M tests/textlib_tests.py
2 files changed, 39 insertions(+), 5 deletions(-)

Approvals:
  Xqt: Looks good to me, approved
  jenkins-bot: Verified




diff --git a/pywikibot/textlib.py b/pywikibot/textlib.py
index 1a34f97..7da87fc 100644
--- a/pywikibot/textlib.py
+++ b/pywikibot/textlib.py
@@ -15,6 +15,7 @@
 from dataclasses import dataclass
 from html.parser import HTMLParser
 from typing import NamedTuple
+from urllib.parse import quote

 import pywikibot
 from pywikibot.backports import pairwise
@@ -2190,15 +2191,33 @@
     section with or without a preceding colon which is required for a
     text link e.g. for categories and files.

+    Legacy dot-escaped titles are matched literally against encoded
+    heading wikitext, treating spaces and underscores alike.
+
+    .. version-changed:: 11.9
+       Legacy dot-escaped section titles are supported.
+
     :param pagetext: The wikitext of a page
     :param section: A section of a page including wikitext markups
     """
     # match preceding colon for text links
-    section = re.sub(r'\\\[\\\[(\\?:)?', r'\[\[\:?', re.escape(section))
+    section_regex = re.sub(
+        r'\\\[\\\[(\\?:)?', r'\[\[\:?', re.escape(section))
     # match underscores and white spaces
-    section = re.sub(r'\\?[ _]', '[ _]', section)
-    m = re.search(f"=+[ ']*{section}[ ']*=+", pagetext)
-    return bool(m)
+    section_regex = re.sub(r'\\?[ _]', '[ _]', section_regex)
+    if re.search(f"=+[ ']*{section_regex}[ ']*=+", pagetext):
+        return True
+
+    # Encode headings instead of decoding ambiguous literal dot sequences.
+    section = section.replace(' ', '_')
+    for match in get_regexes('header')[0].finditer(pagetext):
+        heading = Section(match[1], '').heading.replace(' ', '_')
+        # Legacy anchors escape '~', which quote() always leaves safe.
+        encoded = quote(heading, safe=':').replace('~', '%7E')
+        if encoded.replace('%', '.') == section:
+            return True
+
+    return False


 def reformat_ISBNs(text: str, match_func) -> str:
diff --git a/tests/textlib_tests.py b/tests/textlib_tests.py
index ce008e1..127fa0e 100755
--- a/tests/textlib_tests.py
+++ b/tests/textlib_tests.py
@@ -71,11 +71,26 @@
         self.assertNotContains('Minor_Edits',
                                'section hashes are case-sensitive')

-    @unittest.expectedFailure  # T133276
     def test_encoded_chars_in_section(self) -> None:
         """Test encoded chars in section."""
         self.assertContains('Talk_.28discussion.29_pages',
                             'As used in the TOC')
+        self.assertContains('.5B.5BWiki_markup.5D.5D')
+        self.assertTrue(textlib.does_text_contain_section(
+            '== آزمون ==', '.D8.A2.D8.B2.D9.85.D9.88.D9.86'))
+        self.assertTrue(textlib.does_text_contain_section(
+            '== Literal .28 title ==', 'Literal_.28_title'))
+        self.assertTrue(textlib.does_text_contain_section(
+            '== Version .28 (notes) ==', 'Version_.28_.28notes.29'))
+        self.assertTrue(textlib.does_text_contain_section(
+            '== Invalid .FF title ==', 'Invalid_.FF_title'))
+        self.assertFalse(textlib.does_text_contain_section(
+            '== .27Version (notes) ==', 'Version_.28notes.29'))
+        self.assertFalse(textlib.does_text_contain_section(
+            '== .5B.5B:Help (notes) ==', '.5B.5BHelp_.28notes.29'))
+        self.assertTrue(textlib.does_text_contain_section(
+            '===Version (notes)====', 'Version_.28notes.29.3D'))
+        self.assertNotContains('Talk_%28discussion%29_pages')

     def test_underline_characters_in_section(self) -> None:
         """Test with underline chars in section."""

--
To view, visit 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1346042?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.wikimedia.org/r/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I983df6f7b5606bb39587431554b87503808bb3e9
Gerrit-Change-Number: 1346042
Gerrit-PatchSet: 3
Gerrit-Owner: Mahveotm <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to