jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/705164 )
Change subject: [IMPR] cosmetic_changes.py type hints ......................................................................
[IMPR] cosmetic_changes.py type hints
Bug: T286403 Change-Id: I807cab7b358e89704465909e56242635b9347626 --- M pywikibot/backports.py M pywikibot/cosmetic_changes.py 2 files changed, 62 insertions(+), 43 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/backports.py b/pywikibot/backports.py index 3689416..b565a48 100644 --- a/pywikibot/backports.py +++ b/pywikibot/backports.py @@ -68,12 +68,15 @@ Iterable, List, Mapping, + Match, + Pattern, Sequence, Set, Tuple, ) else: from collections.abc import Callable, Iterable, Mapping, Sequence + from re import Match, Pattern Dict = dict FrozenSet = frozenset List = list diff --git a/pywikibot/cosmetic_changes.py b/pywikibot/cosmetic_changes.py index 11a71e9..bb48a3a 100755 --- a/pywikibot/cosmetic_changes.py +++ b/pywikibot/cosmetic_changes.py @@ -58,10 +58,11 @@ import re
from enum import IntEnum -from typing import Optional +from typing import Any, Optional, Union
import pywikibot from pywikibot import textlib +from pywikibot.backports import Callable, Dict, List, Match, Pattern from pywikibot.exceptions import InvalidTitleError from pywikibot.textlib import ( FILE_LINK_REGEX, @@ -184,7 +185,7 @@ If an error occurred and either skips the page or the method or a single match. ALL raises the exception.
- *New in version 6.3.* + .. versionadded:: 6.3 """
ALL = 0 @@ -193,7 +194,7 @@ MATCH = 3
-def _format_isbn_match(match, strict=True): +def _format_isbn_match(match: Match[str], strict: bool = True) -> str: """Helper function to validate and format a single matched ISBN.""" if not stdnum_isbn: raise NotImplementedError( @@ -211,7 +212,7 @@ return stdnum_isbn.format(isbn)
-def _reformat_ISBNs(text, strict=True): +def _reformat_ISBNs(text: str, strict: bool = True) -> str: """Helper function to normalise ISBNs in text.
:raises Exception: Invalid ISBN encountered when strict enabled @@ -225,15 +226,14 @@ """Cosmetic changes toolkit."""
@deprecated_args(redirect=True, diff='show_diff', site='page') - def __init__(self, page, *, + def __init__(self, page: 'pywikibot.page.BasePage', *, show_diff: bool = False, namespace: Optional[int] = None, pageTitle: Optional[str] = None, - ignore: IntEnum = CANCEL.ALL): + ignore: IntEnum = CANCEL.ALL) -> None: """Initializer.
:param page: the Page object containing the text to be modified - :type page: pywikibot.Page :param show_diff: show difference after replacements (default: False) :param namespace: DEPRECATED namespace parameter :param pageTitle: DEPRECATED page title parameter @@ -292,15 +292,15 @@ if stdnum_isbn: self.common_methods.append(self.fix_ISBN)
- @property + @property # type: ignore[misc] @deprecated('show_diff', since='20200415') - def diff(self): + def diff(self) -> bool: """CosmeticChangesToolkit.diff attribute getter.""" return self.show_diff
- @diff.setter + @diff.setter # type: ignore[misc] @deprecated('show_diff', since='20200415') - def diff(self, value): + def diff(self, value: bool) -> None: """CosmeticChangesToolkit.diff attribute setter.""" self.show_diff = bool(value)
@@ -308,11 +308,13 @@ @deprecated('CosmeticChangesToolkit with pywikibot.Page object', since='20200415') @deprecated_args(diff='show_diff') - def from_page(cls, page, show_diff=False, ignore=CANCEL.ALL): + def from_page(cls, page: 'pywikibot.page.BasePage', + show_diff: bool = False, + ignore: IntEnum = CANCEL.ALL) -> 'CosmeticChangesToolkit': """Create toolkit based on the page.""" return cls(page, show_diff=show_diff, ignore=ignore)
- def safe_execute(self, method, text): + def safe_execute(self, method: Callable[[str], str], text: str) -> str: """Execute the method and catch exceptions if enabled.""" result = None try: @@ -326,13 +328,13 @@ raise return text if result is None else result
- def _change(self, text): + def _change(self, text: str) -> str: """Execute all clean up methods.""" for method in self.common_methods: text = self.safe_execute(method, text) return text
- def change(self, text): + def change(self, text: str) -> Union[bool, str]: """Execute all clean up methods and catch errors if activated.""" try: new_text = self._change(text) @@ -348,7 +350,7 @@ pywikibot.showDiff(text, new_text) return new_text
- def fixSelfInterwiki(self, text): + def fixSelfInterwiki(self, text: str) -> str: """ Interwiki links to the site itself are displayed like local links.
@@ -360,7 +362,7 @@ text = interwikiR.sub(r'[[\1]]', text) return text
- def standardizePageFooter(self, text): + def standardizePageFooter(self, text: str) -> str: """ Standardize page footer.
@@ -382,6 +384,9 @@ if not self.template: categories = textlib.getCategoryLinks(text, site=self.site)
+ if self.title is None: + raise ValueError('Page title required to standardize footer') + if not self.talkpage: subpage = False if self.template: @@ -422,7 +427,7 @@
return text
- def translateAndCapitalizeNamespaces(self, text): + def translateAndCapitalizeNamespaces(self, text: str) -> str: """Use localized namespace names.""" # arz uses English stylish codes if self.site.sitename == 'wikipedia:arz': @@ -482,7 +487,7 @@ exceptions) return text
- def translateMagicWords(self, text): + def translateMagicWords(self, text: str) -> str: """Use localized magic words.""" # not wanted at ru # arz uses English stylish codes @@ -490,7 +495,7 @@ if self.site.code in ['arz', 'en', 'ru']: return text
- def init_cache(): + def init_cache() -> None: for magicword in ('img_thumbnail', 'img_left', 'img_center', 'img_right', 'img_none', 'img_framed', 'img_frameless', 'img_border', 'img_upright', @@ -504,7 +509,7 @@ if not cache: cache[False] = True # signal there is nothing to replace
- def replace_magicword(match): + def replace_magicword(match: Match[str]) -> str: if cache.get(False): return match.group() split = match.group().split('|') @@ -519,7 +524,7 @@ return '{}|{}]]'.format( split[0], '|'.join(cache.get(x.strip(), x) for x in split[1:]))
- cache = {} + cache = {} # type: Dict[Union[bool, str], Any] exceptions = ['comment', 'nowiki', 'pre', 'syntaxhighlight'] regex = re.compile( FILE_LINK_REGEX % '|'.join(self.site.namespaces[6]), @@ -548,7 +553,7 @@ """ # helper function which works on one link and either returns it # unmodified, or returns a replacement. - def handleOneLink(match): + def handleOneLink(match: Match[str]) -> str: titleWithSection = match.group('titleWithSection') label = match.group('label') trailingChars = match.group('linktrail') @@ -681,7 +686,7 @@ 'startspace']) return text
- def resolveHtmlEntities(self, text): + def resolveHtmlEntities(self, text: str) -> str: """Replace HTML entities with string.""" ignore = [ 38, # Ampersand (&) @@ -709,7 +714,7 @@ text, ignore=ignore, exceptions=['comment', 'syntaxhighlight']) return text
- def removeEmptySections(self, text): + def removeEmptySections(self, text: str) -> str: """Cleanup empty sections.""" # userspace contains article stubs without nobots/in use templates if self.namespace == 2: @@ -753,7 +758,7 @@ new_body.extend(sections[i]) return header + ''.join(new_body) + footer
- def removeUselessSpaces(self, text): + def removeUselessSpaces(self, text: str) -> str: """Cleanup multiple or trailing spaces.""" exceptions = ['comment', 'math', 'nowiki', 'pre', 'syntaxhighlight', 'startspace', 'table'] @@ -763,7 +768,7 @@ exceptions, site=self.site) return text
- def removeNonBreakingSpaceBeforePercent(self, text): + def removeNonBreakingSpaceBeforePercent(self, text: str) -> str: """ Remove a non-breaking space between number and percent sign.
@@ -775,7 +780,7 @@ text, r'(\d)&(?:nbsp|#160|#x[Aa]0);%', r'\1 %', ['timeline']) return text
- def cleanUpSectionHeaders(self, text): + def cleanUpSectionHeaders(self, text: str) -> str: """ Add a space between the equal signs and the section title.
@@ -801,7 +806,7 @@ r'\1 \g<title> \1\n', ['comment', 'math', 'nowiki', 'pre'])
- def putSpacesInLists(self, text): + def putSpacesInLists(self, text: str) -> str: """ Add a space between the * or # and the text.
@@ -822,7 +827,7 @@ exceptions) return text
- def replaceDeprecatedTemplates(self, text): + def replaceDeprecatedTemplates(self, text: str) -> str: """Replace deprecated templates.""" exceptions = ['comment', 'math', 'nowiki', 'pre'] builder = MultiTemplateMatchBuilder(self.site) @@ -845,9 +850,9 @@ return text
# from fixes.py - def fixSyntaxSave(self, text): + def fixSyntaxSave(self, text: str) -> str: """Convert weblinks to wikilink, fix link syntax.""" - def replace_link(match): + def replace_link(match: Match[str]) -> str: """Create a string to replace a single link.""" replacement = '[[' if re.match(r'(?:' + '|'.join(list(self.site.namespaces[6]) @@ -913,9 +918,9 @@ r'[\g<url> \g<label>]', exceptions) return text
- def fixHtml(self, text): + def fixHtml(self, text: str) -> str: """Relace html markups with wikitext markups.""" - def replace_header(match): + def replace_header(match: Match[str]) -> str: """Create a header string for replacing.""" depth = int(match.group(1)) return r'{0} {1} {0}'.format('=' * depth, match.group(2)) @@ -945,7 +950,7 @@ # TODO: maybe we can make the bot replace <p> tags with \r\n's. return text
- def fixReferences(self, text): + def fixReferences(self, text: str) -> str: """Fix references tags.""" # See also # https://en.wikipedia.org/wiki/User:AnomieBOT/source/tasks/OrphanReferenceFix... @@ -963,7 +968,7 @@ r'<ref \1/>', exceptions) return text
- def fixStyle(self, text): + def fixStyle(self, text: str) -> str: """Convert prettytable to wikitable class.""" exceptions = ['comment', 'math', 'nowiki', 'pre', 'startspace', 'syntaxhighlight'] @@ -973,10 +978,21 @@ r'\1wikitable\2', exceptions) return text
- def fixTypo(self, text): + def fixTypo(self, text: str) -> str: """Fix units.""" - exceptions = ['comment', 'gallery', 'hyperlink', 'interwiki', 'link', - 'nowiki', 'math', 'pre', 'startspace', 'syntaxhighlight'] + exceptions = [ + 'comment', + 'gallery', + 'hyperlink', + 'interwiki', + 'link', + 'nowiki', + 'math', + 'pre', + 'startspace', + 'syntaxhighlight', + ] # type: List[Union[str, Pattern[str]]] + # change <number> ccm -> <number> cm³ text = textlib.replaceExcept(text, r'(\d)\s*(?: )?ccm', r'\1 cm³', exceptions, @@ -993,7 +1009,7 @@ site=self.site) return text
- def fixArabicLetters(self, text): + def fixArabicLetters(self, text: str) -> str: """Fix Arabic and Persian letters.""" if self.site.code not in ['ckb', 'fa']: return text @@ -1013,7 +1029,7 @@ 'ref', 'startspace', 'syntaxhighlight', - ] + ] # type: List[Union[str, Pattern[str]]]
digits = textlib.NON_LATIN_DIGITS faChrs = 'ءاآأإئؤبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهیةيك' + digits['fa'] @@ -1039,7 +1055,7 @@
return text
- def commonsfiledesc(self, text): + def commonsfiledesc(self, text: str) -> str: """ Clean up file descriptions on Wikimedia Commons.
@@ -1105,7 +1121,7 @@ r'\1== {{int:license-header}} ==', exceptions, True) return text
- def fix_ISBN(self, text): + def fix_ISBN(self, text: str) -> str: """Hyphenate ISBN numbers.""" return _reformat_ISBNs(text, strict=self.ignore != CANCEL.MATCH)
pywikibot-commits@lists.wikimedia.org