jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/749160 )
Change subject: [bugfix] Allow title placeholder $1 in the middle of an url ......................................................................
[bugfix] Allow title placeholder $1 in the middle of an url
- add a new articlepath property which gives a nice article path with placeholder where $1 is replaced by {} for format string usage - deprecate the old article_path property - yield urls with placeholder as format strings BaseSite._interwiki_urls generator - update Family.from_url method to ignore placeholder - update Page.full_url to format the full article path - update fixSyntaxSave method of CosmeticChangesToolkit - Remove workaround patches in pagegenerators.py, fixing_redirects.py solve_disambiguation.py - update family_tests.py - update cosmetic_changes_tests.py
Bug: T298078 Bug: T111513 Change-Id: I03387845ee37f378f09359f32371e0581462467b --- M pywikibot/cosmetic_changes.py M pywikibot/family.py M pywikibot/page/__init__.py M pywikibot/pagegenerators.py M pywikibot/site/_apisite.py M pywikibot/site/_basesite.py M scripts/fixing_redirects.py M scripts/solve_disambiguation.py M tests/cosmetic_changes_tests.py M tests/family_tests.py 10 files changed, 217 insertions(+), 172 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/cosmetic_changes.py b/pywikibot/cosmetic_changes.py index 2f674f7..b3bb6f8 100755 --- a/pywikibot/cosmetic_changes.py +++ b/pywikibot/cosmetic_changes.py @@ -51,7 +51,7 @@ 'your_script_name_2'] """ # -# (C) Pywikibot team, 2006-2021 +# (C) Pywikibot team, 2006-2022 # # Distributed under the terms of the MIT license. # @@ -59,6 +59,7 @@
from enum import IntEnum from typing import Any, Union +from urllib.parse import urlparse, urlunparse
import pywikibot from pywikibot import textlib @@ -519,11 +520,7 @@ trailingChars = match.group('linktrail') newline = match.group('newline')
- try: - is_interwiki = self.site.isInterwikiLink(titleWithSection) - except ValueError: # T111513 - is_interwiki = True - + is_interwiki = self.site.isInterwikiLink(titleWithSection) if is_interwiki: return match.group()
@@ -826,6 +823,7 @@
exceptions = ['comment', 'math', 'nowiki', 'pre', 'startspace', 'syntaxhighlight'] + # link to the wiki working on # Only use suffixes for article paths for suffix in self.site._interwiki_urls(True): @@ -834,31 +832,43 @@ https_url = None else: https_url = self.site.base_url(suffix, 'https') + # compare strings without the protocol, if they are empty support # also no prefix (//en.wikipedia.org/…) - if https_url is not None and http_url[4:] == https_url[5:]: - urls = ['(?:https?:)?' + re.escape(http_url[5:])] + http = urlparse(http_url) + https = urlparse(https_url) + if https_url is not None and http.netloc == https.netloc: + urls = ['(?:https?:)?' + + re.escape(urlunparse(('', *http[1:])))] else: urls = [re.escape(url) for url in (http_url, https_url) if url is not None] + for url in urls: - # Only include links which don't include the separator as - # the wikilink won't support additional parameters - separator = '?' - if '?' in suffix: - separator += '&' + # unescape {} placeholder + url = url.replace(r'{}', '{title}') + + # Only include links which don't include the separator + # as the wikilink won't support additional parameters + separator = '?&' if '?' in suffix else '?' + # Match first a non space in the title to prevent that multiple # spaces at the end without title will be matched by it + title_regex = (r'(?P<link>[^{sep}]+?)' + r'(\s+(?P<title>[^\s].*?))' + .format(sep=separator)) + url_regex = r'[[?{url}?\s*]]?'.format(url=url) text = textlib.replaceExcept( text, - r'[[?' + url + r'(?P<link>[^' + separator + r']+?)' - r'(\s+(?P<title>[^\s].*?))?\s*]]?', + url_regex.format(title=title_regex), replace_link, exceptions, site=self.site) + # external link in/starting with double brackets text = textlib.replaceExcept( text, r'[[(?P<url>https?://[^]]+?)]]?', r'[\g<url>]', exceptions, site=self.site) + # external link and description separated by a pipe, with # whitespace in front of the pipe, so that it is clear that # the dash is not a legitimate part of the URL. @@ -866,6 +876,7 @@ text, r'[(?P<url>https?://[^|] \r\n]+?) +| *(?P<label>[^|]]+?)]', r'[\g<url> \g<label>]', exceptions) + # dash in external link, where the correct end of the URL can # be detected from the file extension. It is very unlikely that # this will cause mistakes. diff --git a/pywikibot/family.py b/pywikibot/family.py index 56a0ad5..e20d90f 100644 --- a/pywikibot/family.py +++ b/pywikibot/family.py @@ -1,6 +1,6 @@ """Objects representing MediaWiki families.""" # -# (C) Pywikibot team, 2004-2021 +# (C) Pywikibot team, 2004-2022 # # Distributed under the terms of the MIT license. # @@ -821,12 +821,12 @@ return config.site_interface
def from_url(self, url: str) -> Optional[str]: - """ - Return whether this family matches the given url. + """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.article_path` and + 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.
@@ -835,13 +835,11 @@ 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 and if it's present nothing is allowed - after it. + 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. - :raises ValueError: When text is present after $1. """ parsed = urlparse.urlparse(url) if not re.match('(https?)?$', parsed.scheme): @@ -852,10 +850,7 @@ path += '?' + parsed.query
# Discard $1 and everything after it - path, _, suffix = path.partition('$1') - if suffix: - raise ValueError('Url: {}\nText {} after the $1 placeholder is ' - 'not supported (T111513).'.format(url, suffix)) + path, *_ = path.partition('$1')
for domain in self.domains: if domain in parsed.netloc: @@ -875,6 +870,7 @@ pywikibot.log('Found candidate {}'.format(site))
for iw_url in site._interwiki_urls(): + iw_url, *_ = iw_url.partition('{}') if path.startswith(iw_url): matched_sites.add(site) break diff --git a/pywikibot/page/__init__.py b/pywikibot/page/__init__.py index 346698d..bd13ca7 100644 --- a/pywikibot/page/__init__.py +++ b/pywikibot/page/__init__.py @@ -385,8 +385,8 @@
def full_url(self): """Return the full URL.""" - return self.site.base_url(self.site.article_path - + self.title(as_url=True)) + return self.site.base_url( + self.site.articlepath.format(self.title(as_url=True)))
def autoFormat(self): """ diff --git a/pywikibot/pagegenerators.py b/pywikibot/pagegenerators.py index 54653cc..84f2643 100644 --- a/pywikibot/pagegenerators.py +++ b/pywikibot/pagegenerators.py @@ -2764,17 +2764,20 @@ yield from google.search(query)
def __iter__(self): - """Iterate results.""" + """Iterate results. + + Google contains links in the format: + https://de.wikipedia.org/wiki/en:Foobar + """ # restrict query to local site localQuery = '{} site:{}'.format(self.query, self.site.hostname()) base = 'http://%7B%7D%7B%7D%27.format(self.site.hostname(), - self.site.article_path) + self.site.articlepath) + pattern = base.replace('{}', '(.+)') for url in self.queryGoogle(localQuery): - if url[:len(base)] == base: - title = url[len(base):] - page = pywikibot.Page(pywikibot.Link(title, self.site)) - # Google contains links in the format - # https://de.wikipedia.org/wiki/en:Foobar + m = re.search(pattern, url) + if m: + page = pywikibot.Page(pywikibot.Link(m.group(1), self.site)) if page.site == self.site: yield page
diff --git a/pywikibot/site/_apisite.py b/pywikibot/site/_apisite.py index 74b45cd..eecca96 100644 --- a/pywikibot/site/_apisite.py +++ b/pywikibot/site/_apisite.py @@ -1,6 +1,6 @@ """Objects representing API interface to MediaWiki site.""" # -# (C) Pywikibot team, 2008-2021 +# (C) Pywikibot team, 2008-2022 # # Distributed under the terms of the MIT license. # @@ -624,12 +624,26 @@ in ['1', True]}
@property + @deprecated('articlepath', since='7.0.0') def article_path(self): - """Get the nice article path without $1.""" - # Assert and remove the trailing $1 and assert that it'll end in / - assert self.siteinfo['general']['articlepath'].endswith('/$1'), \ - 'articlepath must end with /$1' - return self.siteinfo['general']['articlepath'][:-2] + """Get the nice article path without $1. + + .. deprecated:: 7.0 + Replaced by :py:meth:`articlepath` + """ + return self.articlepath[:-2] + + @property + def articlepath(self): + """Get the nice article path with placeholder. + + .. versionadded:: 7.0 + Replaces :py:meth:`article_path` + """ + # Assert $1 placeholder is present + path = self.siteinfo['general']['articlepath'] + assert '$1' in path, 'articlepath must contain "$1" placeholder' + return path.replace('$1', '{}')
@staticmethod def assert_valid_iter_params(msg_prefix, start, end, reverse, diff --git a/pywikibot/site/_basesite.py b/pywikibot/site/_basesite.py index 8856d35..db86186 100644 --- a/pywikibot/site/_basesite.py +++ b/pywikibot/site/_basesite.py @@ -1,6 +1,6 @@ """Objects with site methods independent of the communication interface.""" # -# (C) Pywikibot team, 2008-2021 +# (C) Pywikibot team, 2008-2022 # # Distributed under the terms of the MIT license. # @@ -233,10 +233,10 @@ def _interwiki_urls(self, only_article_suffixes=False): base_path = self.path() if not only_article_suffixes: - yield base_path - yield base_path + '/' - yield base_path + '?title=' - yield self.article_path + yield base_path + '{}' + yield base_path + '/{}' + yield base_path + '?title={}' + yield self.articlepath
def _build_namespaces(self): """Create default namespaces.""" diff --git a/scripts/fixing_redirects.py b/scripts/fixing_redirects.py index 6fc4ef1..42e0df7 100755 --- a/scripts/fixing_redirects.py +++ b/scripts/fixing_redirects.py @@ -77,12 +77,9 @@ break # Make sure that next time around we will not find this same hit. curpos = m.start() + 1 - # T283403 - try: - is_interwikilink = mysite.isInterwikiLink(m.group('title')) - except ValueError: - pywikibot.exception() - continue + + is_interwikilink = mysite.isInterwikiLink(m.group('title')) + # ignore interwiki links, links in the disabled area # and links to sections of the same page if (m.group('title').strip() == '' diff --git a/scripts/solve_disambiguation.py b/scripts/solve_disambiguation.py index 16506b1..fac2821 100755 --- a/scripts/solve_disambiguation.py +++ b/scripts/solve_disambiguation.py @@ -899,7 +899,7 @@ foundlink = pywikibot.Link(m.group('title'), disamb_page.site) foundlink.parse() - except (Error, ValueError): # T111513 + except Error: continue
# ignore interwiki links diff --git a/tests/cosmetic_changes_tests.py b/tests/cosmetic_changes_tests.py index 61d1996..b0f8fed 100644 --- a/tests/cosmetic_changes_tests.py +++ b/tests/cosmetic_changes_tests.py @@ -1,6 +1,6 @@ """Test cosmetic_changes module.""" # -# (C) Pywikibot team, 2015-2021 +# (C) Pywikibot team, 2015-2022 # # Distributed under the terms of the MIT license. # @@ -9,6 +9,8 @@
from pywikibot import Page from pywikibot.cosmetic_changes import CosmeticChangesToolkit +from pywikibot.site._namespace import NamespacesDict + from tests.aspects import TestCase
@@ -22,7 +24,7 @@ @classmethod def setUpClass(cls): """Setup class for all tests.""" - super(TestCosmeticChanges, cls).setUpClass() + super().setUpClass() cls.cct = CosmeticChangesToolkit(Page(cls.site, 'Test'))
@@ -137,100 +139,6 @@ '{{Quellen_fehlen|foo}}' ))
- def test_fixSyntaxSave(self): - """Test fixSyntaxSave method.""" - # necessary as the fixer needs the article path to fix it - self.cct.site._siteinfo._cache['general'] = ( - {'articlepath': '/wiki/$1'}, True) - self.cct.site._namespaces = { - 6: ['Datei', 'File'], - 14: ['Kategorie', 'Category'], - } - self.assertEqual( - '[[Example|Page]]\n[[Example|Page]]\n[[Example|Page]]\n' - '[[Example]]\n[[Example]]\n[[Example]]\n' - '[https://de.wikipedia.org/w/index.php?title=Example&' - 'oldid=68181978 Page]\n' - '[https://de.wikipedia.org/w/index.php?title=Example&' - 'oldid=68181978&diff=next Page]\n' - '[https://en.wikipedia.org/w/index.php?title=Example%5D%5Cn' - '[https://de.wiktionary.org/w/index.php?title=Example%5D%5Cn', - self.cct.fixSyntaxSave( - '[https://de.wikipedia.org/w/index.php?title=Example Page]\n' - '[https://de.wikipedia.org/w/index.php?title=Example Page ]\n' - '[https://de.wikipedia.org/w/index.php?title=Example Page ]\n' - '[https://de.wikipedia.org/w/index.php?title=Example%5D%5Cn' - '[https://de.wikipedia.org/w/index.php?title=Example ]\n' - '[https://de.wikipedia.org/w/index.php?title=Example ]\n' - '[https://de.wikipedia.org/w/index.php?title=Example&' - 'oldid=68181978 Page]\n' - '[https://de.wikipedia.org/w/index.php?title=Example&' - 'oldid=68181978&diff=next Page]\n' - '[https://en.wikipedia.org/w/index.php?title=Example%5D%5Cn' - '[https://de.wiktionary.org/w/index.php?title=Example%5D%5Cn' - )) - self.assertEqual( - '[[Example]]\n[[Example]]\n[[Example]]\n' - '[https://de.wikipedia.org/wiki/Example?oldid=68181978 Page]\n' - '[https://de.wikipedia.org/wiki/Example?' - 'oldid=68181978&diff=next Page]\n' - '[[Example]]\n[[Example]]\n[[Example]]\n' - '[https://de.wikipedia.org/w/index.php/Example?' - 'oldid=68181978 Page]\n' - '[https://de.wikipedia.org/w/index.php/Example?' - 'oldid=68181978&diff=next Page]\n' - '[[&]]\n[[&]]\n', - self.cct.fixSyntaxSave( - '[https://de.wikipedia.org/wiki/Example%5D%5Cn' - '[https://de.wikipedia.org/wiki/Example ]\n' - '[https://de.wikipedia.org/wiki/Example ]\n' - '[https://de.wikipedia.org/wiki/Example?oldid=68181978 Page]\n' - '[https://de.wikipedia.org/wiki/Example?' - 'oldid=68181978&diff=next Page]\n' - '[https://de.wikipedia.org/w/index.php/Example%5D%5Cn' - '[https://de.wikipedia.org/w/index.php/Example ]\n' - '[https://de.wikipedia.org/w/index.php/Example ]\n' - '[https://de.wikipedia.org/w/index.php/Example?' - 'oldid=68181978 Page]\n' - '[https://de.wikipedia.org/w/index.php/Example?' - 'oldid=68181978&diff=next Page]\n' - '[https://de.wikipedia.org/wiki/&%5D%5Cn' - '[https://de.wikipedia.org/w/index.php/&%5D%5Cn' - )) - self.assertEqual( - '[https://de.wikipedia.org]', - self.cct.fixSyntaxSave('[[https://de.wikipedia.org]]')) - self.assertEqual( - '[https://de.wikipedia.org]', - self.cct.fixSyntaxSave('[[https://de.wikipedia.org]')) - self.assertEqual( - '[https://de.wikipedia.org/w/api.php API]', - self.cct.fixSyntaxSave('[https://de.wikipedia.org/w/api.php%7CAPI]')) - self.assertEqual( - '[[:Kategorie:Example]]\n' - '[[:Category:Example|Description]]\n' - '[[:Datei:Example.svg]]\n' - '[[:File:Example.svg|Description]]\n' - '[[:Category:Example]]\n' - '[[:Kategorie:Example|Description]]\n' - '[[:File:Example.svg]]\n' - '[[:Datei:Example.svg|Description]]\n', - self.cct.fixSyntaxSave( - '[https://de.wikipedia.org/wiki/Kategorie:Example%5D%5Cn' - '[https://de.wikipedia.org/wiki/Category:Example ' - 'Description]\n' - '[https://de.wikipedia.org/wiki/Datei:Example.svg%5D%5Cn' - '[https://de.wikipedia.org/wiki/File:Example.svg ' - 'Description]\n' - '[[https://de.wikipedia.org/wiki/Category:Example%5D%5D%5Cn' - '[[https://de.wikipedia.org/wiki/Kategorie:Example ' - 'Description]]\n' - '[[https://de.wikipedia.org/wiki/File:Example.svg%5D%5D%5Cn' - '[[https://de.wikipedia.org/wiki/Datei:Example.svg ' - 'Description]]\n' - )) - del self.cct.site._namespaces - def test_fixHtml(self): """Test fixHtml method.""" self.assertEqual("'''Foo''' bar", @@ -273,6 +181,126 @@ self.assertEqual(text, self.cct.fixArabicLetters(text))
+class TestDryFixSyntaxSave(TestCosmeticChanges): + + """Test fixSyntaxSave not requiring a live wiki.""" + + dry = True + + @classmethod + def setUpClass(cls): + """Setup class for all tests.""" + super().setUpClass() + cls.cct.site._siteinfo._cache['general'] = ( + {'articlepath': '/wiki/$1'}, True) + cls.cct.site._namespaces = NamespacesDict({ + 6: ['Datei', 'File'], + 14: ['Kategorie', 'Category'], + }) + + def test_title_param(self): + """Test fixing url with title parameter.""" + # necessary as the fixer needs the article path to fix it + self.assertEqual( + '[[Example|Page]]\n[[Example|Page]]\n[[Example|Page]]\n' + '[[Example]]\n[[Example]]\n[[Example]]\n' + '[https://de.wikipedia.org/w/index.php?title=Example&' + 'oldid=68181978 Page]\n' + '[https://de.wikipedia.org/w/index.php?title=Example&' + 'oldid=68181978&diff=next Page]\n' + '[https://en.wikipedia.org/w/index.php?title=Example%5D%5Cn' + '[https://de.wiktionary.org/w/index.php?title=Example%5D%5Cn', + self.cct.fixSyntaxSave( + '[https://de.wikipedia.org/w/index.php?title=Example Page]\n' + '[https://de.wikipedia.org/w/index.php?title=Example Page ]\n' + '[https://de.wikipedia.org/w/index.php?title=Example Page ]\n' + '[https://de.wikipedia.org/w/index.php?title=Example%5D%5Cn' + '[https://de.wikipedia.org/w/index.php?title=Example ]\n' + '[https://de.wikipedia.org/w/index.php?title=Example ]\n' + '[https://de.wikipedia.org/w/index.php?title=Example&' + 'oldid=68181978 Page]\n' + '[https://de.wikipedia.org/w/index.php?title=Example&' + 'oldid=68181978&diff=next Page]\n' + '[https://en.wikipedia.org/w/index.php?title=Example%5D%5Cn' + '[https://de.wiktionary.org/w/index.php?title=Example%5D%5Cn' + )) + + def test_fix_url(self): + """Test fixing urls.""" + self.assertEqual( + '[[Example]]\n[[Example]]\n[[Example]]\n' + '[https://de.wikipedia.org/wiki/Example?oldid=68181978 Page]\n' + '[https://de.wikipedia.org/wiki/Example?' + 'oldid=68181978&diff=next Page]\n' + '[[Example]]\n[[Example]]\n[[Example]]\n' + '[https://de.wikipedia.org/w/index.php/Example?' + 'oldid=68181978 Page]\n' + '[https://de.wikipedia.org/w/index.php/Example?' + 'oldid=68181978&diff=next Page]\n' + '[[&]]\n[[&]]\n', + self.cct.fixSyntaxSave( + '[https://de.wikipedia.org/wiki/Example%5D%5Cn' + '[https://de.wikipedia.org/wiki/Example ]\n' + '[https://de.wikipedia.org/wiki/Example ]\n' + '[https://de.wikipedia.org/wiki/Example?oldid=68181978 Page]\n' + '[https://de.wikipedia.org/wiki/Example?' + 'oldid=68181978&diff=next Page]\n' + '[https://de.wikipedia.org/w/index.php/Example%5D%5Cn' + '[https://de.wikipedia.org/w/index.php/Example ]\n' + '[https://de.wikipedia.org/w/index.php/Example ]\n' + '[https://de.wikipedia.org/w/index.php/Example?' + 'oldid=68181978 Page]\n' + '[https://de.wikipedia.org/w/index.php/Example?' + 'oldid=68181978&diff=next Page]\n' + '[https://de.wikipedia.org/wiki/&%5D%5Cn' + '[https://de.wikipedia.org/w/index.php/&%5D%5Cn' + )) + + def test_fix_brackets(self): + """Test fixing brackets.""" + self.assertEqual( + '[https://de.wikipedia.org]', + self.cct.fixSyntaxSave('[[https://de.wikipedia.org]]')) + + def test_fix_missing_bracket(self): + """Test fixing missing bracket.""" + self.assertEqual( + '[https://de.wikipedia.org]', + self.cct.fixSyntaxSave('[[https://de.wikipedia.org]')) + + def test_fix_link_text(self): + """Test fixing link text.""" + self.assertEqual( + '[https://de.wikipedia.org/w/api.php API]', + self.cct.fixSyntaxSave('[https://de.wikipedia.org/w/api.php%7CAPI]')) + + def test_fix_files_and_categories(self): + """Test files and categories fix.""" + self.assertEqual( + '[[:Kategorie:Example]]\n' + '[[:Category:Example|Description]]\n' + '[[:Datei:Example.svg]]\n' + '[[:File:Example.svg|Description]]\n' + '[[:Category:Example]]\n' + '[[:Kategorie:Example|Description]]\n' + '[[:File:Example.svg]]\n' + '[[:Datei:Example.svg|Description]]\n', + self.cct.fixSyntaxSave( + '[https://de.wikipedia.org/wiki/Kategorie:Example%5D%5Cn' + '[https://de.wikipedia.org/wiki/Category:Example ' + 'Description]\n' + '[https://de.wikipedia.org/wiki/Datei:Example.svg%5D%5Cn' + '[https://de.wikipedia.org/wiki/File:Example.svg ' + 'Description]\n' + '[[https://de.wikipedia.org/wiki/Category:Example%5D%5D%5Cn' + '[[https://de.wikipedia.org/wiki/Kategorie:Example ' + 'Description]]\n' + '[[https://de.wikipedia.org/wiki/File:Example.svg%5D%5D%5Cn' + '[[https://de.wikipedia.org/wiki/Datei:Example.svg ' + 'Description]]\n' + )) + + class TestLiveCosmeticChanges(TestCosmeticChanges):
"""Test cosmetic_changes requiring a live wiki.""" diff --git a/tests/family_tests.py b/tests/family_tests.py index 6f5cb63..bcaea49 100644 --- a/tests/family_tests.py +++ b/tests/family_tests.py @@ -1,6 +1,6 @@ """Tests for the family module.""" # -# (C) Pywikibot team, 2014-2021 +# (C) Pywikibot team, 2014-2022 # # Distributed under the terms of the MIT license. # @@ -160,14 +160,14 @@ self.assertEqual(code, self.current_code) self.assertEqual(fam, self.current_family) site = DrySite(code, fam, None) - site._siteinfo._cache['general'] = ({'articlepath': self.article_path}, + site._siteinfo._cache['general'] = ({'articlepath': self.articlepath}, True) return site
def setUp(self): """Setup default article path.""" super().setUp() - self.article_path = '/wiki/$1' + self.articlepath = '/wiki/$1'
def test_from_url_wikipedia_extra(self): """Test various URLs against wikipedia regex.""" @@ -191,12 +191,8 @@ self.assertEqual(f.from_url(prefix + '/wiki/Main_page'), 'vo') self.assertEqual(f.from_url(prefix + '/w/index.php?title=Foo'), 'vo')
- # Text after $1 is not allowed - with self.assertRaisesRegex( - ValueError, - 'Url: .+\nText /foo after the ' - r'$1 placeholder is not supported (T111513).'): - f.from_url('//vo.wikipedia.org/wiki/$1/foo') + # Text after $1 is allowed + self.assertEqual(f.from_url('//vo.wikipedia.org/wiki/$1/foo'), 'vo')
# the IWM may contain the wrong protocol, but it's only used to # determine a site so using HTTP or HTTPS is not an issue @@ -216,20 +212,20 @@ def test_each_family(self): """Test each family builds a working regex.""" for family in pywikibot.config.family_files: - with self.subTest(family=family): - if family == 'wowwiki': - self.skipTest( - 'Family.from_url() does not work for {} (T215077)' - .format(family)) - self.current_family = family - family = Family.load(family) - for code in family.codes: - self.current_code = code - url = ('{}://{}{}/$1'.format(family.protocol(code), - family.hostname(code), - family.path(code))) - # Families can switch off if they want to be detected using - # URL. This applies for test:test (there is test:wikipedia) + if family == 'wowwiki': + self.skipTest( + 'Family.from_url() does not work for {} (T215077)' + .format(family)) + self.current_family = family + family = Family.load(family) + for code in family.codes: + self.current_code = code + url = ('{}://{}{}/$1'.format(family.protocol(code), + family.hostname(code), + family.path(code))) + # Families can switch off if they want to be detected using + # URL. This applies for test:test (there is test:wikipedia) + with self.subTest(url=url): self.assertEqual(family.from_url(url), code)
pywikibot-commits@lists.wikimedia.org