jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1112370?usp=email )
Change subject: login.py: Recognise * in config.usernames
......................................................................
login.py: Recognise * in config.usernames
If there is an '*' in config.usernames as the language for a certain family,
expand it to all codes that are found in the family file if the code is not
already given.
Note: you may use -async to speed-up login process.
Bug: T110411
Change-Id: I5af62457d34709209c3a4ce76e54bb603e3729a3
---
M pywikibot/scripts/login.py
1 file changed, 19 insertions(+), 5 deletions(-)
Approvals:
jenkins-bot: Verified
Xqt: Looks good to me, approved
diff --git a/pywikibot/scripts/login.py b/pywikibot/scripts/login.py
index c1af7f6..eacc7f9 100755
--- a/pywikibot/scripts/login.py
+++ b/pywikibot/scripts/login.py
@@ -41,10 +41,14 @@
subdirectory.
.. versionchanged:: 7.4
- moved to :mod:`pywikibot.scripts` folder
+ moved to :mod:`pywikibot.scripts` folder.
+.. versionchanged:: 7.7
+ *-async* option was added.
+.. versionchanged:: 10.2
+ wildcard site codes in ``usernames`` dict are supported.
"""
#
-# (C) Pywikibot team, 2003-2024
+# (C) Pywikibot team, 2003-2025
#
# Distributed under the terms of the MIT license.
#
@@ -56,6 +60,7 @@
import pywikibot
from pywikibot import config
from pywikibot.exceptions import NoUsernameError, SiteDefinitionError
+from pywikibot.family import Family
from pywikibot.login import OauthLoginManager
from pywikibot.tools.threading import BoundedPoolExecutor
@@ -161,11 +166,20 @@
BoundedPoolExecutor('ThreadPoolExecutor'))[asynchronous]
with context as executor:
for family_name in namedict:
- for lang in namedict[family_name]:
+ family_codes = namedict[family_name]
+
+ if '*' in family_codes:
+ user = family_codes['*']
+ del family_codes['*']
+ codes = (code for code in Family.load(family_name).codes
+ if code not in family_codes)
+ family_codes.update(dict.fromkeys(codes, user))
+
+ for code in family_codes:
if asynchronous:
- executor.submit(login_one_site, lang, family_name, *params)
+ executor.submit(login_one_site, code, family_name, *params)
else:
- login_one_site(lang, family_name, *params)
+ login_one_site(code, family_name, *params)
if __name__ == '__main__':
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1112370?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: I5af62457d34709209c3a4ce76e54bb603e3729a3
Gerrit-Change-Number: 1112370
Gerrit-PatchSet: 6
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Dalba <dalba.wiki(a)gmail.com>
Gerrit-Reviewer: Framawiki <framawiki(a)tools.wmflabs.org>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1154488?usp=email )
Change subject: [BUG] exturlusage: protocol can't be a list
......................................................................
[BUG] exturlusage: protocol can't be a list
Change-Id: I66d697546268560953a888e6a5e88a9554f0adc6
---
M pywikibot/site/_generators.py
M tests/site_generators_tests.py
2 files changed, 9 insertions(+), 22 deletions(-)
Approvals:
JJMC89: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/site/_generators.py b/pywikibot/site/_generators.py
index debd456..fe44f35 100644
--- a/pywikibot/site/_generators.py
+++ b/pywikibot/site/_generators.py
@@ -1317,7 +1317,7 @@
def exturlusage(
self,
url: str | None = None,
- protocol: str | list[str] | None = None,
+ protocol: str | None = None,
namespaces: NamespaceArgType = None,
total: int | None = None,
content: bool = False,
@@ -1331,11 +1331,9 @@
of the hostname
:param namespaces: list of namespace numbers to fetch contribs from
:param total: Maximum number of pages to retrieve in total
- :param protocol: list of protocols to search for, http and https by
- default. Full list shown on Special:LinkSearch wikipage
+ :param protocol: protocol to search for, http and https by default.
+ Full list shown on Special:LinkSearch wikipage
"""
- if isinstance(protocol, str):
- protocol = [protocol]
if url is not None:
found_protocol, _, url = url.rpartition('://')
@@ -1345,18 +1343,12 @@
url = None
if found_protocol:
- if protocol:
- if len(protocol) > 1:
- raise ValueError(
- 'More than one protocol was specified and a '
- 'protocol was found in searched url'
- )
- if protocol[0] != found_protocol:
- raise ValueError(
- f'Protocol {protocol!r} was specified, but '
- f'{found_protocol!r} was found in searched url'
- )
- protocol = [found_protocol]
+ if protocol and protocol != found_protocol:
+ raise ValueError(
+ f'Protocol {protocol!r} was specified, but '
+ f'{found_protocol!r} was found in searched url'
+ )
+ protocol = found_protocol
return self._generator(api.PageGenerator, type_arg='exturlusage',
geuquery=url, geuprotocol=protocol,
diff --git a/tests/site_generators_tests.py b/tests/site_generators_tests.py
index 7bf8655..8ee081f 100755
--- a/tests/site_generators_tests.py
+++ b/tests/site_generators_tests.py
@@ -596,11 +596,6 @@
mysite.exturlusage('https://www.google.com', protocol='http')
with self.assertRaises(ValueError):
mysite.exturlusage('http://www.google.com', protocol='https')
- with self.assertRaises(ValueError):
- mysite.exturlusage(
- 'https://www.google.com',
- protocol=['http', 'https'],
- )
def test_protectedpages_create(self) -> None:
"""Test that protectedpages returns protected page titles."""
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1154488?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: I66d697546268560953a888e6a5e88a9554f0adc6
Gerrit-Change-Number: 1154488
Gerrit-PatchSet: 1
Gerrit-Owner: JJMC89 <JJMC89.Wikimedia(a)gmail.com>
Gerrit-Reviewer: JJMC89 <JJMC89.Wikimedia(a)gmail.com>
Gerrit-Reviewer: jenkins-bot
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1152437?usp=email )
Change subject: IMPR: replace codecs.open() with open() in parser_function_count.py
......................................................................
IMPR: replace codecs.open() with open() in parser_function_count.py
Bug: T395187
Change-Id: I57225980e75ab26fbe3806cb60e7bfdbe024f32a
---
M scripts/parser_function_count.py
1 file changed, 2 insertions(+), 7 deletions(-)
Approvals:
Xqt: Looks good to me, approved
jenkins-bot: Verified
diff --git a/scripts/parser_function_count.py b/scripts/parser_function_count.py
index 5900508..60c02ed 100755
--- a/scripts/parser_function_count.py
+++ b/scripts/parser_function_count.py
@@ -43,13 +43,12 @@
functions will be listed.
"""
#
-# (C) Pywikibot team, 2013-2022
+# (C) Pywikibot team, 2013-2025
#
# Distributed under the terms of the MIT license.
#
from __future__ import annotations
-import codecs
import re
from collections import Counter
@@ -163,12 +162,8 @@
# File operations:
if self.opt.save:
- # This opens in strict error mode, that means bot will stop
- # on encoding errors with ValueError.
- # See https://docs.python.org/3/library/codecs.html#codecs.open
try:
- with codecs.open(
- self.opt.save, encoding='utf-8', mode='a') as f:
+ with open(self.opt.save, 'a', encoding='utf-8') as f:
f.write(resultlist)
except OSError as e:
pywikibot.error(e)
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1152437?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: I57225980e75ab26fbe3806cb60e7bfdbe024f32a
Gerrit-Change-Number: 1152437
Gerrit-PatchSet: 2
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1154390?usp=email )
Change subject: [Bugfix] Fix i18n.translate calls
......................................................................
[Bugfix] Fix i18n.translate calls
i18n.translate() does not raise a KeyError if the key does not exists
but just returns None. Therefore use the following variants:
- suppress TypeError if the result is to be unpacked in more than one
variable
- check whether the result is None to continue
- add additional checks to solve_disambiguation.py
Bug: T219094
Change-Id: Iae2ac3af3229be160940062f3f2f14d6050ec435
---
M pywikibot/cosmetic_changes.py
M scripts/category.py
M scripts/commonscat.py
M scripts/imagetransfer.py
M scripts/interwiki.py
M scripts/solve_disambiguation.py
6 files changed, 47 insertions(+), 55 deletions(-)
Approvals:
jenkins-bot: Verified
Meno25: Looks good to me, but someone else must approve
Lichinsol: Looks good to me, but someone else must approve
Xqt: Looks good to me, approved
diff --git a/pywikibot/cosmetic_changes.py b/pywikibot/cosmetic_changes.py
index ffc66cd..c397430 100644
--- a/pywikibot/cosmetic_changes.py
+++ b/pywikibot/cosmetic_changes.py
@@ -50,7 +50,7 @@
'your_script_name_2']
"""
#
-# (C) Pywikibot team, 2006-2024
+# (C) Pywikibot team, 2006-2025
#
# Distributed under the terms of the MIT license.
#
@@ -373,11 +373,9 @@
if not self.talkpage:
subpage = False
if self.template:
- try:
- tmpl, loc = i18n.translate(self.site.code, moved_links)
- del tmpl
- except KeyError:
- loc = None
+ loc = None
+ with suppress(TypeError):
+ _tmpl, loc = i18n.translate(self.site.code, moved_links)
if loc is not None and loc in self.title:
subpage = True
diff --git a/scripts/category.py b/scripts/category.py
index 7cd95e1..100b4ef 100755
--- a/scripts/category.py
+++ b/scripts/category.py
@@ -153,7 +153,7 @@
:mod:`pagegenerators` are supported with "move" and "remove" action.
"""
#
-# (C) Pywikibot team, 2004-2024
+# (C) Pywikibot team, 2004-2025
#
# Distributed under the terms of the MIT license.
#
@@ -301,7 +301,7 @@
return page
tmpl: Sequence = []
- with suppress(KeyError):
+ with suppress(TypeError):
tmpl, _loc = i18n.translate(page.site.code, moved_links)
if not isinstance(tmpl, list):
diff --git a/scripts/commonscat.py b/scripts/commonscat.py
index 1c7c4e0..298a8ba 100755
--- a/scripts/commonscat.py
+++ b/scripts/commonscat.py
@@ -40,7 +40,7 @@
# *Found one template. Add this template
# *Found more templates. Ask the user <- still have to implement this
#
-# (C) Pywikibot team, 2008-2024
+# (C) Pywikibot team, 2008-2025
#
# Distributed under the terms of the MIT license.
#
@@ -260,10 +260,8 @@
@staticmethod
def skipPage(page) -> bool:
"""Determine if the page should be skipped."""
- try:
- templates_to_ignore = i18n.translate(page.site.code,
- ignoreTemplates)
- except KeyError:
+ templates_to_ignore = i18n.translate(page.site.code, ignoreTemplates)
+ if not templates_to_ignore:
return False
for template in templates_to_ignore:
diff --git a/scripts/imagetransfer.py b/scripts/imagetransfer.py
index a1820a7..89855f9 100755
--- a/scripts/imagetransfer.py
+++ b/scripts/imagetransfer.py
@@ -43,7 +43,7 @@
¶ms;
"""
#
-# (C) Pywikibot team, 2004-2024
+# (C) Pywikibot team, 2004-2025
#
# Distributed under the terms of the MIT license.
#
@@ -206,7 +206,7 @@
:return: the filename which was used to upload the image
"""
- def delete_source(old_filename, target_filename):
+ def delete_source(_old_filename: str, target_filename: str) -> None:
"""Delete source image or tag nowCommons template to it.
This function is called when upload to Commons was
@@ -223,16 +223,14 @@
and sourceImagePage.delete(reason):
return
- if sourceSite.lang in nowCommonsTemplate \
- and sourceSite.family.name in config.usernames \
- and sourceSite.lang in config.usernames[sourceSite.family.name]:
+ tmpl = i18n.translate(sourceSite.code, nowCommonsTemplate)
+ if tmpl and sourceSite.family.name in config.usernames \
+ and sourceSite.code in config.usernames[sourceSite.family.name]:
# add the nowCommons template.
pywikibot.info('Adding nowCommons template to '
+ sourceImagePage.title())
sourceImagePage.put(sourceImagePage.get() + '\n\n'
- + i18n.translate(sourceSite.code,
- nowCommonsTemplate)
- % target_filename,
+ + tmpl % target_filename,
summary=reason)
sourceSite = sourceImagePage.site
diff --git a/scripts/interwiki.py b/scripts/interwiki.py
index e357276..de7913c 100755
--- a/scripts/interwiki.py
+++ b/scripts/interwiki.py
@@ -343,7 +343,7 @@
``-continue`` next time.
"""
#
-# (C) Pywikibot team, 2003-2024
+# (C) Pywikibot team, 2003-2025
#
# Distributed under the terms of the MIT license.
#
@@ -1864,9 +1864,8 @@
continue
if page.namespace() == 10:
loc = None
- with suppress(KeyError):
- tmpl, loc = i18n.translate(page.site.code, moved_links)
- del tmpl
+ with suppress(TypeError):
+ _tpl, loc = i18n.translate(page.site.code, moved_links)
if loc is not None and loc in page.title():
pywikibot.info(
f'Skipping: {page.title()} is a templates subpage')
@@ -2084,19 +2083,18 @@
def botMayEdit(page) -> bool:
"""Test for allowed edits."""
tmpl = []
- with suppress(KeyError):
+ with suppress(TypeError):
tmpl, _ = i18n.translate(page.site.code, moved_links)
if not isinstance(tmpl, list):
tmpl = [tmpl]
- with suppress(KeyError):
- tmpl += i18n.translate(page.site.code, ignoreTemplates,
- fallback=i18n.DEFAULT_FALLBACK)
+ with suppress(TypeError):
+ tmpl += i18n.translate(page.site.code, ignoreTemplates)
- tmpl += i18n.translate('_default', ignoreTemplates,
- fallback=i18n.DEFAULT_FALLBACK)
- if tmpl != []:
+ tmpl += i18n.translate('_default', ignoreTemplates)
+
+ if tmpl:
templates = page.templatesWithParams()
for template in templates:
if template[0].title(with_ns=False).lower() in tmpl:
diff --git a/scripts/solve_disambiguation.py b/scripts/solve_disambiguation.py
index ef114b1..fd530e8 100755
--- a/scripts/solve_disambiguation.py
+++ b/scripts/solve_disambiguation.py
@@ -74,7 +74,7 @@
"""
#
-# (C) Pywikibot team, 2003-2024
+# (C) Pywikibot team, 2003-2025
#
# Distributed under the terms of the MIT license.
#
@@ -1025,24 +1025,25 @@
:return: True if everything goes fine, False otherwise
"""
if page.isRedirectPage() and not self.opt.primary:
+ topic = None
primary = i18n.translate(page.site,
self.primary_redir_template)
if primary:
- primary_page = pywikibot.Page(page.site,
- 'Template:' + primary)
- if primary and primary_page in page.itertemplates(
+ primary_page = pywikibot.Page(page.site, 'Template:' + primary)
+ topic = i18n.translate(self.site.code, primary_topic_format)
+
+ if topic and primary_page in page.itertemplates(
namespaces=Namespace.TEMPLATE):
baseTerm = page.title()
for template, params in page.templatesWithParams():
if params and template == primary_page:
baseTerm = params[1]
break
- disambTitle = i18n.translate(
- self.site.lang,
- primary_topic_format) % baseTerm
+
+ disamb_title = topic % baseTerm
try:
page2 = pywikibot.Page(
- pywikibot.Link(disambTitle, self.site))
+ pywikibot.Link(disamb_title, self.site))
links = page2.linkedPages()
if self.opt.first:
links = self.firstize(page2, links)
@@ -1050,7 +1051,7 @@
for link in links]
except NoPageError:
pywikibot.info(
- f'No page at {disambTitle}, using redirect target.')
+ f'No page at {disamb_title}, using redirect target.')
links = page.linkedPages()[:1]
links = [correctcap(link,
page.get(get_redirect=True))
@@ -1065,34 +1066,30 @@
user_input = pywikibot.input("""\
Please enter the name of the page where the redirect should have pointed at,
or press enter to quit:""")
- if user_input == '':
- self.quit()
- else:
- self.opt.pos.append(user_input)
+ if not user_input:
+ self.quit() # raises QuitKeyboardInterrupt
+
+ self.opt.pos.append(user_input)
except IsNotRedirectPageError:
pywikibot.info(
'The specified page is not a redirect. Skipping.')
return False
+
elif self.opt.just:
# not page.isRedirectPage() or self.opt.primary
try:
- if self.opt.primary:
+ topic = i18n.translate(self.site.lang, primary_topic_format)
+ if topic and self.opt.primary:
try:
- page2 = pywikibot.Page(
- pywikibot.Link(
- i18n.translate(self.site.lang,
- primary_topic_format)
- % page.title(),
- self.site))
+ page2 = pywikibot.Page(self.site, topic % page.title())
links = page2.linkedPages()
if self.opt.first:
links = self.firstize(page2, links)
links = [correctcap(link, page2.get())
for link in links]
except NoPageError:
- pywikibot.info(
- 'Page does not exist; using first '
- f'link in page {page.title()}.')
+ pywikibot.info('Page does not exist; using first '
+ f'link in page {page.title()}.')
links = page.linkedPages()[:1]
links = [correctcap(link, page.get())
for link in links]
@@ -1106,10 +1103,13 @@
except NoPageError:
pywikibot.info('Page does not exist, skipping.')
return False
+
except IsRedirectPageError:
pywikibot.info('Page is a redirect, skipping.')
return False
+
self.opt.pos += links
+
return True
def setSummaryMessage(
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1154390?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: Iae2ac3af3229be160940062f3f2f14d6050ec435
Gerrit-Change-Number: 1154390
Gerrit-PatchSet: 1
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Lichinsol <vaibhavjoshi1411(a)gmail.com>
Gerrit-Reviewer: Meno25 <meno25mail(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot