Xqt submitted this change.

View Change

Approvals: jenkins-bot: Verified Xqt: Looks good to me, approved
[IMPR] use keyword arguments with solve_disambiguation.py

Also deprecate bot attributes in favour of 'opt' options settings

Change-Id: I0590ded8382aab083e52e1c2dd8a13371cf712e6
---
M scripts/solve_disambiguation.py
1 file changed, 205 insertions(+), 48 deletions(-)

diff --git a/scripts/solve_disambiguation.py b/scripts/solve_disambiguation.py
index b3c8428..91c3c17 100755
--- a/scripts/solve_disambiguation.py
+++ b/scripts/solve_disambiguation.py
@@ -75,7 +75,7 @@

"""
#
-# (C) Pywikibot team, 2003-2020
+# (C) Pywikibot team, 2003-2021
#
# Distributed under the terms of the MIT license.
#
@@ -95,7 +95,9 @@
from pywikibot.backports import List
from pywikibot.bot import (HighlightContextOption, ListOption,
OutputProxyOption, SingleSiteBot, StandardOption)
-from pywikibot.tools import first_lower, first_upper
+from pywikibot.tools import (
+ deprecated, first_lower, first_upper, issue_deprecation_warning,
+)
from pywikibot.tools.formatter import SequenceOutputter

# Disambiguation Needed template
@@ -598,25 +600,180 @@
'hu': 'Egyért-redir',
}

- def __init__(self, always, alternatives, getAlternatives, dnSkip,
- generator, primary, main_only, first_only=False, minimum=0,
- **kwargs) -> None:
+ # refer -help message for complete options documentation
+ disambig_options = {
+ 'always': None, # always perform the same action
+ 'pos': [], # add possibilities as alternative disambig
+ 'just': True, # just and only use the possibilities given with command
+ 'dnskip': False, # skip already marked links
+ 'primary': False, # primary topic disambig
+ 'main': False, # only use main namespace
+ 'first': False, # use first link only
+ 'min': 0, # minimum number of pages on a disambig
+ }
+
+ # needed for argument cleanup
+ available_options = disambig_options
+
+ def __init__(self, *args, **kwargs) -> None:
"""Initializer."""
+ self._clean_args(args, kwargs)
super().__init__(**kwargs)
- self.always = always
- self.alternatives = alternatives
- self.getAlternatives = getAlternatives
- self.dnSkip = dnSkip
- if generator:
- self.generator = generator
- self.primary = primary
self.ignores = set()
- self.main_only = main_only
- self.first_only = first_only
- self.minimum = minimum
self.summary = None
self.dn_template_str = i18n.translate(self.site, dn_template)

+ def _clean_args(self, args, kwargs):
+ """Cleanup positional and keyword arguments.
+
+ Replace positional arguments with keyword arguments.
+ Replace old keywords with new keywords which are given by
+ argument handling.
+
+ This also fixes arguments which aren't currently used by
+ BaseDisambigBot abstract class but was introduced for the old
+ DisambiguationRobot to prevent multiple deprecation warnings.
+ """
+ # New keys of positional arguments
+ keys = ('always', 'pos', 'just', 'dnskip', 'generator', 'primary',
+ 'main', 'first', 'min')
+
+ # Keys mapping from old argument name to new keywords.
+ # The ordering of dics is not safe for Python < 3.7. Therefore
+ # we need a dict in addition to key above.
+ keymap = {
+ 'alternatives': 'pos',
+ 'getAlternatives': 'just',
+ 'dnSkip': 'dnskip',
+ 'main_only': 'main',
+ 'first_only': 'first',
+ 'minimum': 'min',
+ }
+
+ # Replace positional arguments with keyword arguments
+ for i, arg in enumerate(args):
+ key = keys[i]
+ issue_deprecation_warning(
+ 'Positional argument {} ({})'.format(i + 1, arg),
+ 'keyword argument "{}={}"'.format(key, arg),
+ since='20210303')
+ if key in kwargs:
+ pywikibot.warning('{!r} is given as keyword argument {!r} '
+ 'already; ignoring {!r}'
+ .format(key, arg, kwargs[key]))
+ else:
+ kwargs[key] = arg
+
+ # replace old keywords to new
+ for key in list(kwargs):
+ if key in keymap:
+ newkey = keymap[key]
+ issue_deprecation_warning(
+ '{!r} argument of {}'.format(key, self.__class__.__name__),
+ repr(newkey), since='20210303')
+ kwargs[newkey] = kwargs.pop(key)
+
+ # Expand available_options
+ # Currently scripts may have its own options set
+ added_keys = []
+ for key in keys:
+ if key != 'generator':
+ if key not in self.available_options:
+ added_keys.append(key)
+ self.available_options[key] = self.disambig_options[key]
+ if added_keys:
+ pywikibot.warning("""\
+The following keys were added to available_options:
+{options}.
+Either add them to available_options setting of {classname}
+bot class or use available_options.update() to use default settings from
+DisambiguationRobot""".format(options=added_keys,
+ classname=self.__class__.__name__))
+
+ # Deprecated properties ---------------------------------------
+
+ @property
+ @deprecated('opt.always', since='20210303', future_warning=True)
+ def always(self): # noqa: D102
+ return self.opt.always
+
+ @always.setter
+ @deprecated('opt.always', since='20210303', future_warning=True)
+ def always(self, value):
+ self.opt.always = value
+
+ @property
+ @deprecated('opt.dnskip', since='20210303', future_warning=True)
+ def dnSkip(self): # noqa: D102
+ return self.opt.dnskip
+
+ @dnSkip.setter
+ @deprecated('opt.dnskip', since='20210303', future_warning=True)
+ def dnSkip(self, value):
+ self.opt.dnskip = value
+
+ @property
+ @deprecated('opt.primary', since='20210303', future_warning=True)
+ def primary(self): # noqa: D102
+ return self.opt.primary
+
+ @primary.setter
+ @deprecated('opt.primary', since='20210303', future_warning=True)
+ def primary(self, value):
+ self.opt.primary = value
+
+ @property
+ @deprecated('opt.main', since='20210303', future_warning=True)
+ def main_only(self): # noqa: D102
+ return self.opt.main
+
+ @main_only.setter
+ @deprecated('opt.main', since='20210303', future_warning=True)
+ def main_only(self, value):
+ self.opt.main = value
+
+ @property
+ @deprecated('opt.first', since='20210303', future_warning=True)
+ def first_only(self): # noqa: D102
+ return self.opt.first
+
+ @first_only.setter
+ @deprecated('opt.first', since='20210303', future_warning=True)
+ def first_only(self, value):
+ self.opt.first = value
+
+ @property
+ @deprecated('opt.min', since='20210303', future_warning=True)
+ def minimum(self): # noqa: D102
+ return self.opt.min
+
+ @minimum.setter
+ @deprecated('opt.min', since='20210303', future_warning=True)
+ def minimum(self, value):
+ self.opt.min = value
+
+ @property
+ @deprecated('opt.pos', since='20210303', future_warning=True)
+ def alternatives(self): # noqa: D102
+ return self.opt.pos
+
+ @alternatives.setter
+ @deprecated('opt.pos', since='20210303', future_warning=True)
+ def alternatives(self, value):
+ self.opt.pos = value
+
+ @property
+ @deprecated('opt.just', since='20210303', future_warning=True)
+ def getAlternatives(self): # noqa: D102
+ return self.opt.just
+
+ @getAlternatives.setter
+ @deprecated('opt.just', since='20210303', future_warning=True)
+ def getAlternatives(self, value):
+ self.opt.just = value
+
+ # -------------------------------------------------------------
+
def checkContents(self, text: str) -> Optional[str]: # noqa: N802
"""
Check if the text matches any of the ignore regexes.
@@ -633,13 +790,13 @@
return None

def makeAlternativesUnique(self) -> None: # noqa: N802
- """Remove duplicate items from self.alternatives.
+ """Remove duplicate items from self.opt.pos.

Preserve the order of alternatives.
"""
seen = set()
- self.alternatives = [i for i in self.alternatives
- if i not in seen and not seen.add(i)]
+ self.opt.pos = [i for i in self.opt.pos
+ if i not in seen and not seen.add(i)]

def setup(self) -> None:
"""Compile regular expressions."""
@@ -750,7 +907,7 @@
pywikibot.output('{0} is a redirect to {1}'
.format(ref_page.title(), disamb_page.title()))
if disamb_page.isRedirectPage():
- target = self.alternatives[0]
+ target = self.opt.pos[0]
if pywikibot.input_yn(
'Do you want to make redirect {0} point to {1}?'
.format(ref_page.title(), target),
@@ -771,7 +928,7 @@
automatic_quit=False)
if choice == 'y':
gen = ReferringPageGeneratorWithIgnore(
- ref_page, self.primary, main_only=self.main_only
+ ref_page, self.opt.primary, main_only=self.opt.main
)
gen = pagegenerators.PreloadingGenerator(gen)
for ref_page2 in gen:
@@ -842,7 +999,7 @@
context = 60

# check if there's a dn-template here already
- if (self.dnSkip and self.dn_template_str
+ if (self.opt.dnskip and self.dn_template_str
and self.dn_template_str[:-2] in text[
m.end():m.end() + len(self.dn_template_str) + 8]):
continue
@@ -854,8 +1011,8 @@
end=m.end())
context_option.before_question = True

- options = [ListOption(self.alternatives, ''),
- ListOption(self.alternatives, 'r'),
+ options = [ListOption(self.opt.pos, ''),
+ ListOption(self.opt.pos, 'r'),
StandardOption('skip link', 's'),
edit,
StandardOption('next page', 'n'),
@@ -874,16 +1031,16 @@

options += [
OutputProxyOption('list', 'l',
- SequenceOutputter(self.alternatives)),
+ SequenceOutputter(self.opt.pos)),
AddAlternativeOption('add new', 'a',
- SequenceOutputter(self.alternatives))]
+ SequenceOutputter(self.opt.pos))]
if edited:
options += [StandardOption('save in this form', 'x')]

# TODO: Output context on each question
answer = pywikibot.input_choice('Option', options,
- default=self.always,
- force=bool(self.always))
+ default=self.opt.always,
+ force=bool(self.opt.always))
if answer == 'x':
assert edited, 'invalid option before editing'
break
@@ -900,7 +1057,7 @@

if answer == 'n':
# skip this page
- if self.primary:
+ if self.opt.primary:
# If run with the -primary argument, skip this
# occurrence next time.
self.ignores.add(ref_page.title(as_url=True))
@@ -1019,13 +1176,13 @@
return 'done'

def findAlternatives(self, page) -> bool: # noqa: N802
- """Extend self.alternatives using correctcap of disambPage.linkedPages.
+ """Extend self.opt.pos using correctcap of disambPage.linkedPages.

@param page: the disambiguation page
@type page: pywikibot.Page
@return: True if everything goes fine, False otherwise
"""
- if page.isRedirectPage() and not self.primary:
+ if page.isRedirectPage() and not self.opt.primary:
primary = i18n.translate(page.site,
self.primary_redir_template)
if primary:
@@ -1042,7 +1199,7 @@
page2 = pywikibot.Page(
pywikibot.Link(disambTitle, self.site))
links = page2.linkedPages()
- if self.first_only:
+ if self.opt.first:
links = self.firstize(page2, links)
links = [correctcap(link, page2.get())
for link in links]
@@ -1053,11 +1210,11 @@
links = [correctcap(link,
page.get(get_redirect=True))
for link in links]
- self.alternatives += links
+ self.opt.pos += links
else:
try:
target = page.getRedirectTarget().title()
- self.alternatives.append(target)
+ self.opt.pos.append(target)
except pywikibot.NoPage:
pywikibot.output('The specified page was not found.')
user_input = pywikibot.input("""\
@@ -1066,15 +1223,15 @@
if user_input == '':
self.quit()
else:
- self.alternatives.append(user_input)
+ self.opt.pos.append(user_input)
except pywikibot.IsNotRedirectPage:
pywikibot.output(
'The specified page is not a redirect. Skipping.')
return False
- elif self.getAlternatives:
- # not page.isRedirectPage() or self.primary
+ elif self.opt.just:
+ # not page.isRedirectPage() or self.opt.primary
try:
- if self.primary:
+ if self.opt.primary:
try:
page2 = pywikibot.Page(
pywikibot.Link(
@@ -1082,7 +1239,7 @@
% page.title(),
self.site))
links = page2.linkedPages()
- if self.first_only:
+ if self.opt.first:
links = self.firstize(page2, links)
links = [correctcap(link, page2.get())
for link in links]
@@ -1096,7 +1253,7 @@
else:
try:
links = page.linkedPages()
- if self.first_only:
+ if self.opt.first:
links = self.firstize(page, links)
links = [correctcap(link, page.get())
for link in links]
@@ -1106,7 +1263,7 @@
except pywikibot.IsRedirectPage:
pywikibot.output('Page is a redirect, skipping.')
return False
- self.alternatives += links
+ self.opt.pos += links
return True

def setSummaryMessage(self, page, new_targets=None, unlink_counter=0,
@@ -1182,7 +1339,7 @@
def treat(self, page) -> None:
"""Work on a single disambiguation page."""
self.primaryIgnoreManager = PrimaryIgnoreManager(
- page, enabled=self.primary)
+ page, enabled=self.opt.primary)

if not self.findAlternatives(page):
return
@@ -1191,16 +1348,16 @@
self.makeAlternativesUnique()
# sort possible choices
if config.sort_ignore_case:
- self.alternatives.sort(key=lambda x: x.lower())
+ self.opt.pos.sort(key=lambda x: x.lower())
else:
- self.alternatives.sort()
- SequenceOutputter(self.alternatives).output()
+ self.opt.pos.sort()
+ SequenceOutputter(self.opt.pos).output()

gen = ReferringPageGeneratorWithIgnore(
page,
- self.primary,
- minimum=self.minimum,
- main_only=self.main_only
+ self.opt.primary,
+ minimum=self.opt.min,
+ main_only=self.opt.main
)
gen = pagegenerators.PreloadingGenerator(gen)
for ref_page in gen:
@@ -1209,7 +1366,7 @@
break # next disambig

# clear alternatives before working on next disambiguation page
- self.alternatives = []
+ self.opt.pos = []


def main(*args: Tuple[str, ...]) -> None:

To view, visit change 668044. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I0590ded8382aab083e52e1c2dd8a13371cf712e6
Gerrit-Change-Number: 668044
Gerrit-PatchSet: 5
Gerrit-Owner: Xqt <info@gno.de>
Gerrit-Reviewer: D3r1ck01 <xsavitar.wiki@aol.com>
Gerrit-Reviewer: DannyS712 <dannys712.wiki@gmail.com>
Gerrit-Reviewer: Xqt <info@gno.de>
Gerrit-Reviewer: jenkins-bot
Gerrit-CC: JAn Dudík <jan.dudik@gmail.com>
Gerrit-CC: Matěj Suchánek <matejsuchanek97@gmail.com>
Gerrit-MessageType: merged