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

Change subject: [bugfix] Enable url without api, requests or script path in 
Site constuctor
......................................................................

[bugfix] Enable url without api, requests or script path in Site constuctor

Enable url with empty path of urllib.parse.ParseResult in Site
constructor and Family.from_url method. This means that
//commons.wikimedia.org is a valid url for them. The previous
implementation requires a valid path e.g. //meta.wikimedia.org/w/api.php
with apipath.

Therefore if path of the URL scheme is empty, do not check for any
site._interwiki_urls() which holds all possible paths.

Some tests added.

Bug: T386665
Change-Id: Icd538fe05005e02d1061e30b8e160018218fe986
---
M pywikibot/__init__.py
M pywikibot/family.py
M tests/basesite_tests.py
M tests/family_tests.py
4 files changed, 48 insertions(+), 21 deletions(-)

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




diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 2f6c4c0..9449596 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -171,6 +171,9 @@
     .. versionchanged:: 7.3
        Short creation if site code is equal to family name like
        `Site('commons')`, `Site('meta')` or `Site('wikidata')`.
+    .. versionchanged:: 10.0
+       *url* does not have to contain an api, requests or script path
+       any longer.

     :param code: language code (override config.mylang)
         code may also be a sitename like 'wikipedia:test'
diff --git a/pywikibot/family.py b/pywikibot/family.py
index 70d1934..77e8da6 100644
--- a/pywikibot/family.py
+++ b/pywikibot/family.py
@@ -1,6 +1,6 @@
 """Objects representing MediaWiki families."""
 #
-# (C) Pywikibot team, 2004-2024
+# (C) Pywikibot team, 2004-2025
 #
 # Distributed under the terms of the MIT license.
 #
@@ -579,23 +579,27 @@
     def from_url(self, url: str) -> str | None:
         """Return whether this family matches the given url.

-        It is first checking if a domain of this family is in the domain of
-        the URL. If that is the case it's checking all codes and verifies that
-        a path generated via
-        :py:obj:`APISite.articlepath<pywikibot.site.APISite.articlepath>` and
-        :py:obj:`Family.path` matches the path of the URL together with
-        the hostname for that code.
+        It is first checking if a domain of this family is in the domain
+        of the URL. If that is the case it's checking all codes and
+        verifies that a path generated via :attr:`APISite.articlepath
+        <pywikibot.site.APISite.articlepath>` and :attr:`Family.path`
+        matches the path of the URL together with the hostname for that
+        code.

-        It is using :py:obj:`Family.domains` to first check if a domain
-        applies and then iterates over :py:obj:`Family.codes` to actually
+        It is using :attr:`Family.domains` to first check if a domain
+        applies and then iterates over :attr:`Family.codes` to actually
         determine which code applies.

-        :param url: the URL which may contain a ``$1``. If it's missing it is
-            assumed to be at the end.
-        :return: The language code of the url. None if that url is not from
-            this family.
-        :raises RuntimeError: When there are multiple languages in this family
-            which would work with the given URL.
+        .. versionchanged:: 10.0
+           *url* parameter does not have to contain a api/query/script
+           path
+
+        :param url: the URL which may contain a ``$1``. If it's missing
+            it is assumed to be at the end.
+        :return: The language code of the URL. None if that URL is not
+            from his family.
+        :raises RuntimeError: When there are multiple languages in this
+            family which would work with the given URL.
         """
         parsed = urlparse.urlparse(url)
         if parsed.scheme not in {'http', 'https', ''}:
@@ -625,6 +629,9 @@
                 site = pywikibot.Site(code, self.name)
                 pywikibot.log(f'Found candidate {site}')

+                if not path:
+                    return site.code
+
                 for iw_url in site._interwiki_urls():
                     iw_url, *_ = iw_url.partition('{}')
                     if path.startswith(iw_url):
diff --git a/tests/basesite_tests.py b/tests/basesite_tests.py
index 1c7b497..eae3719 100755
--- a/tests/basesite_tests.py
+++ b/tests/basesite_tests.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 """Tests for the site module."""
 #
-# (C) Pywikibot team, 2008-2024
+# (C) Pywikibot team, 2008-2025
 #
 # Distributed under the terms of the MIT license.
 #
@@ -129,6 +129,20 @@
         self.assertTrue(mysite.sametitle('MediaWiki:Always',
                                          'MediaWiki:always'))

+    def test_site_with_url(self):
+        """Test site constructor with url."""
+        for fam in ('commons', 'meta'):
+            with self.subTest(family=fam):
+                site = pywikibot.Site(url=f'https://{fam}.wikimedia.org')
+                self.assertEqual(site, pywikibot.Site(fam))
+                self.assertEqual(site.family.name, fam)
+                self.assertEqual(site.code, fam)
+
+        site = pywikibot.Site(url='https://fr.wikipedia.org')
+        self.assertEqual(site, pywikibot.Site('wikipedia:fr'))
+        self.assertEqual(site.family.name, 'wikipedia')
+        self.assertEqual(site.code, 'fr')
+

 if __name__ == '__main__':
     with suppress(SystemExit):
diff --git a/tests/family_tests.py b/tests/family_tests.py
index 68e52ba..3bfa9ac 100755
--- a/tests/family_tests.py
+++ b/tests/family_tests.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 """Tests for the family module."""
 #
-# (C) Pywikibot team, 2014-2024
+# (C) Pywikibot team, 2014-2025
 #
 # Distributed under the terms of the MIT license.
 #
@@ -168,8 +168,8 @@
         super().setUp()
         self.articlepath = '/wiki/$1'

-    def test_from_url_wikipedia_extra(self):
-        """Test various URLs against wikipedia regex."""
+    def test_from_url(self):
+        """Test various URLs for Family.from_url."""
         self.current_code = 'vo'
         self.current_family = 'wikipedia'

@@ -181,6 +181,8 @@
         self.assertEqual(f.from_url(prefix + '/w/index.php'), 'vo')
         self.assertEqual(f.from_url(prefix + '/w/index.php/'), 'vo')
         self.assertEqual(f.from_url(prefix + '/w/index.php?title=$1'), 'vo')
+        # url without scripts/api path
+        self.assertEqual(f.from_url(prefix), 'vo')

         self.assertEqual(f.from_url(prefix + '/wiki/$1'), 'vo')
         self.assertEqual(f.from_url('//vo.wikipedia.org/wiki/$1'), 'vo')
@@ -218,10 +220,11 @@
             family = Family.load(family)
             for code in family.codes:
                 self.current_code = code
-                url = (f'{family.protocol(code)}://{family.hostname(code)}'
-                       f'{family.path(code)}/$1')
+                url = f'{family.protocol(code)}://{family.hostname(code)}'
+                url_with_path = url + f'{family.path(code)}/$1'
                 with self.subTest(url=url):
                     self.assertEqual(family.from_url(url), code)
+                    self.assertEqual(family.from_url(url_with_path), code)


 if __name__ == '__main__':

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

Reply via email to