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

Change subject: page: Do not validate sections in BasePage.get
......................................................................

page: Do not validate sections in BasePage.get

BasePage.get retrieves the complete page text regardless of a title
fragment. Move the existing best-effort raw-wikitext check to the
opt-in strict redirect path so ignore_section=False remains functional.

Bug: T422856
Bug: T422859
Change-Id: Ia86ddae21bb52e4bc8948a7bb984ebb5b15d663c
---
M ROADMAP.rst
M pywikibot/page/_basepage.py
M pywikibot/page/_page.py
M pywikibot/page/_wikibase.py
M pywikibot/site/_apisite.py
M tests/page_tests.py
6 files changed, 134 insertions(+), 32 deletions(-)

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




diff --git a/ROADMAP.rst b/ROADMAP.rst
index 941279c..3e7ad59 100644
--- a/ROADMAP.rst
+++ b/ROADMAP.rst
@@ -4,6 +4,9 @@
 * Update translations (i18n)
 * Add new :class:`family.WikimediaSubdomainFamily`
 * Update documentation for :meth:`page.BasePage.exists`. (:phab:`T334341`)
+* :meth:`page.BasePage.get` no longer validates section fragments or raises
+  :exc:`exceptions.SectionError` for them (:phab:`T422856`,
+  :phab:`T422859`).

 Deprecations
 ============
diff --git a/pywikibot/page/_basepage.py b/pywikibot/page/_basepage.py
index d7b4e4a..020c5d1 100644
--- a/pywikibot/page/_basepage.py
+++ b/pywikibot/page/_basepage.py
@@ -379,8 +379,10 @@
         pywikibot.exceptions.IsRedirectPageError: ... is a redirect page.

         .. version-changed:: 9.2
-           :exc:`exceptions.SectionError` is raised if the
-           :meth:`section` does not exist
+           Added validation for the section in the page title.
+        .. version-changed:: 11.8
+           A title fragment neither selects nor validates a section; the
+           complete page text is returned.
         .. seealso:: :attr:`text` property

         :param force: Reload all page attributes, including errors.
@@ -388,8 +390,6 @@
             redirect, do not raise an exception.
         :raises NoPageError: The page does not exist.
         :raises IsRedirectPageError: The page is a redirect.
-        :raises SectionError: The section does not exist on a page with
-            a # link.
         """
         if force:
             del self.latest_revision_id
@@ -401,17 +401,7 @@
             if not get_redirect:
                 raise

-        text = self.latest_revision.text
-
-        # check for valid section in title
-        page_section = self.section()
-        if page_section:
-            content = textlib.extract_sections(text, self.site)
-            if page_section not in content.sections:
-                raise SectionError(f'{page_section!r} is not a valid section '
-                                   f'of {self.title(with_section=False)}')
-
-        return text
+        return self.latest_revision.text

     def has_content(self) -> bool:
         """Page has been loaded.
@@ -2026,16 +2016,16 @@
              <pywikibot.site._apisite.APISite.getredirtarget>`
            * :meth:`moved_target`

-        :param ignore_section: Do not include section to the target even
-            the link has one
+        :param ignore_section: Skip checking the target section against raw
+            wikitext headings.

         :raises CircularRedirectError: Page is a circular redirect
         :raises InterwikiRedirectPageError: The redirect target is on
             another site
         :raises IsNotRedirectPageError: Page is not a redirect
         :raises RuntimeError: No redirects found
-        :raises SectionError: The section is not found on target page
-            and *ignore_section* is not set
+        :raises SectionError: The section does not match a raw wikitext
+            heading on the target page and *ignore_section* is not set
         """
         return self.site.getredirtarget(self, ignore_section=ignore_section)

diff --git a/pywikibot/page/_page.py b/pywikibot/page/_page.py
index ea213bc..6c1de70 100644
--- a/pywikibot/page/_page.py
+++ b/pywikibot/page/_page.py
@@ -23,6 +23,7 @@
     IsNotRedirectPageError,
     IsRedirectPageError,
     NoPageError,
+    SectionError,
     UnknownExtensionError,
 )
 from pywikibot.page._basepage import BasePage
@@ -45,6 +46,28 @@
                              'if source is a Site.')
         super().__init__(source, title, ns)

+    def _check_section(self) -> None:
+        """Check the title section against headings in the raw wikitext.
+
+        This best-effort check supports strict redirect-target handling; it
+        does not reproduce MediaWiki's parser-generated anchors.
+
+        :raises SectionError: The section does not match an extracted heading.
+        """
+        page_section = self.section()
+        if not page_section:
+            return
+
+        try:
+            text = self.get(get_redirect=True)
+        except NoPageError:
+            return
+
+        content = textlib.extract_sections(text, self.site)
+        if page_section not in content.sections:
+            raise SectionError(f'{page_section!r} is not a valid section '
+                               f'of {self.title(with_section=False)}')
+
     @property
     @cached
     def raw_extracted_templates(self):
diff --git a/pywikibot/page/_wikibase.py b/pywikibot/page/_wikibase.py
index 87a0217..4403d57 100644
--- a/pywikibot/page/_wikibase.py
+++ b/pywikibot/page/_wikibase.py
@@ -1165,8 +1165,8 @@

         .. seealso:: :meth:`page.BasePage.getRedirectTarget`

-        :param ignore_section: Do not include section to the target even
-            the link has one
+        :param ignore_section: Skip checking the target section against raw
+            wikitext headings.

         :raises CircularRedirectError: Page is a circular redirect
         :raises InterwikiRedirectPageError: The redirect target is on
@@ -1174,8 +1174,8 @@
         :raises Error: Target page has wrong content model
         :raises IsNotRedirectPageError: Page is not a redirect
         :raises RuntimeError: No redirects found
-        :raises SectionError: The section is not found on target page
-            and *ignore_section* is not set
+        :raises SectionError: The section does not match a raw wikitext
+            heading on the target page and *ignore_section* is not set
         """
         target = super().getRedirectTarget(ignore_section=ignore_section)
         cmodel = target.content_model
diff --git a/pywikibot/site/_apisite.py b/pywikibot/site/_apisite.py
index c2d2303..012e909 100644
--- a/pywikibot/site/_apisite.py
+++ b/pywikibot/site/_apisite.py
@@ -1633,8 +1633,8 @@
         .. seealso:: :meth:`page.BasePage.getRedirectTarget`

         :param page: Page to search redirects for
-        :param ignore_section: Do not include section to the target even
-            the link has one
+        :param ignore_section: Skip checking the target section against raw
+            wikitext headings.
         :return: Redirect target of page

         :raises CircularRedirectError: Page is a circular redirect
@@ -1642,8 +1642,8 @@
             another site
         :raises IsNotRedirectPageError: Page is not a redirect
         :raises RuntimeError: No redirects found
-        :raises SectionError: The section is not found on target page
-            and *ignore_section* is not set
+        :raises SectionError: The section does not match a raw wikitext
+            heading on the target page and *ignore_section* is not set
         """
         if not self.page_isredirect(page):
             raise IsNotRedirectPageError(page)
@@ -1726,8 +1726,7 @@
             target = pywikibot.Category(target)

         if not ignore_section:
-            # get the content; this raises SectionError if section is not found
-            target.text
+            target._check_section()

         page._redirtarget = target
         return page._redirtarget
diff --git a/tests/page_tests.py b/tests/page_tests.py
index 3f158cd..b12547f 100755
--- a/tests/page_tests.py
+++ b/tests/page_tests.py
@@ -186,6 +186,95 @@
         section.assert_called_once_with()


+class TestPageGet(DefaultSiteTestCase):
+
+    """Test retrieving page text."""
+
+    dry = True
+
+    def _page_with_text(self, title: str, text: str) -> pywikibot.Page:
+        """Return a page with cached *text*."""
+        page = pywikibot.Page(self.site, title)
+        page._revid = 1
+        page._isredir = False
+        page._revisions[1] = pywikibot.page.Revision(
+            revid=1, slots={'main': {'*': text}})
+        return page
+
+    def test_get_does_not_validate_section(self) -> None:
+        """Test that get does not inspect a title section."""
+        text = '== Existing ==\nText'
+        page = self._page_with_text('Test#Missing', text)
+
+        with mock.patch.object(page, 'section') as section:
+            self.assertEqual(page.get(), text)
+        section.assert_not_called()
+
+    def test_text_section_regressions(self) -> None:
+        """Test parser-normalized headings do not affect page text."""
+        cases = (
+            (
+                'T422856',
+                'Test#Radio stations in India by state',
+                '==== Radio stations  in India by state ====\nContent',
+            ),
+            (
+                'T411307',
+                'Test#Japanese superhero films by decade',
+                '==== Japanese superhero films\u200e by decade ====\nContent',
+            ),
+        )
+
+        for task, title, text in cases:
+            with self.subTest(task=task):
+                page = self._page_with_text(title, text)
+                self.assertEqual(page.text, text)
+
+    def test_check_section(self) -> None:
+        """Test explicit section validation."""
+        page = self._page_with_text('Test#Existing', '== Existing ==\nText')
+        page._check_section()
+
+        page = self._page_with_text('Test#Missing', '== Existing ==\nText')
+
+        with self.assertRaisesRegex(SectionError,
+                                    "'Missing' is not a valid section"):
+            page._check_section()
+
+    def test_check_section_missing_page(self) -> None:
+        """Test strict redirect checking preserves a missing target."""
+        page = pywikibot.Page(self.site, 'Missing#Section')
+        page._getexception = NoPageError(page)
+
+        page._check_section()
+
+    def test_redirect_target_checks_section(self) -> None:
+        """Test explicit redirect section validation is preserved."""
+        page = pywikibot.Page(self.site, 'Redirect')
+        page._isredir = True
+        data = {
+            'query': {
+                'redirects': [{
+                    'from': 'Redirect',
+                    'to': 'Target',
+                    'tofragment': 'Section',
+                }],
+                'pages': {'1': {'title': 'Target'}},
+            },
+        }
+        request = mock.Mock()
+        request.submit.return_value = data
+
+        with mock.patch.object(self.site, 'simple_request',
+                               return_value=request):
+            with mock.patch.object(
+                    pywikibot.Page, '_check_section') as check_section:
+                target = page.getRedirectTarget(ignore_section=False)
+
+        self.assertEqual(target.title(), 'Target#Section')
+        check_section.assert_called_once_with()
+
+
 class TestPageObjectEnglish(TestCase):

     """Test Page Object using English Wikipedia."""
@@ -1052,9 +1141,7 @@
             p3.get()

         page = pywikibot.Page(site, 'User:Legoktm/R2#Section')
-        with self.assertRaisesRegex(SectionError,
-                                    "'Section' is not a valid section"):
-            page.get()
+        self.assertEqual(page.get(), text)

         site = pywikibot.Site('mediawiki')
         page = pywikibot.Page(site, 'Manual:Pywikibot/2.0 #See_also')

--
To view, visit 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1328725?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: Ia86ddae21bb52e4bc8948a7bb984ebb5b15d663c
Gerrit-Change-Number: 1328725
Gerrit-PatchSet: 3
Gerrit-Owner: Mahveotm <[email protected]>
Gerrit-Reviewer: JJMC89 <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to