jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/934674 )
Change subject: [IMPR] Use f-strings within pywikibot
......................................................................
[IMPR] Use f-strings within pywikibot
Changes made by flint 0.78
Change-Id: I55d8a55ef7d526ac9f32b40ce131073c08697cdc
---
M pywikibot/exceptions.py
M pywikibot/data/sparql.py
M docs/conf.py
M pywikibot/logentries.py
M pywikibot/pagegenerators/_filters.py
M pywikibot/pagegenerators/_generators.py
M pywikibot/site/_datasite.py
M pywikibot/page/_wikibase.py
M pywikibot/data/api/_optionset.py
M pywikibot/comms/eventstreams.py
M pywikibot/page/_links.py
M pywikibot/scripts/generate_family_file.py
M pywikibot/data/api/_paraminfo.py
M pywikibot/scripts/version.py
M pywikibot/config.py
M pywikibot/scripts/shell.py
M pywikibot/page/_collections.py
M pywikibot/textlib.py
M pywikibot/version.py
M pywikibot/site/_generators.py
M pywikibot/scripts/preload_sites.py
M pywikibot/date.py
M pywikibot/page/_user.py
M pywikibot/page/_decorators.py
M pywikibot/data/memento.py
M pywikibot/login.py
M pywikibot/tools/djvu.py
M pywikibot/specialbots/_upload.py
M pywikibot/tools/chars.py
M pywikibot/site/_obsoletesites.py
M pywikibot/family.py
M pywikibot/page/_category.py
M pywikibot/page/_basepage.py
M pywikibot/scripts/wrapper.py
M pywikibot/site/_extensions.py
M pywikibot/userinterfaces/terminal_interface_base.py
M pywikibot/i18n.py
M pywikibot/page/_filepage.py
M pywikibot/tools/threading.py
M pywikibot/scripts/generate_user_files.py
M pywikibot/site/_upload.py
M pywikibot/bot.py
M pywikibot/tools/__init__.py
M pywikibot/__init__.py
M pywikibot/bot_choice.py
M pywikibot/interwiki_graph.py
M pywikibot/time.py
M pywikibot/comms/http.py
M pywikibot/diff.py
M pywikibot/pagegenerators/_factory.py
M pywikibot/tools/_deprecate.py
M pywikibot/site/_basesite.py
M pywikibot/data/api/_generators.py
M pywikibot/proofreadpage.py
54 files changed, 247 insertions(+), 341 deletions(-)
Approvals:
JJMC89: Looks good to me, approved
jenkins-bot: Verified
diff --git a/docs/conf.py b/docs/conf.py
index 786fecc..6a3f9c2 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -526,7 +526,7 @@
for index, line in enumerate(lines):
# highlight the first line
if index == 0: # highlight the first line
- lines[0] = '**{}**'.format(line.strip('.'))
+ lines[0] = f"**{line.strip('.')}**"
# add link for pagegenerators options
elif line == '¶ms;':
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 2b376c3..e17528f 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -148,8 +148,7 @@
if not self._entity:
if self.globe not in self.site.globes():
raise exceptions.CoordinateGlobeUnknownError(
- '{} is not supported in Wikibase yet.'
- .format(self.globe))
+ f'{self.globe} is not supported in Wikibase yet.')
return self.site.globes()[self.globe]
if isinstance(self._entity, ItemPage):
@@ -435,8 +434,7 @@
if site is None:
site = Site().data_repository()
if site is None:
- raise ValueError('Site {} has no data repository'
- .format(Site()))
+ raise ValueError(f'Site {Site()} has no data repository')
calendarmodel = site.calendarmodel()
self.calendarmodel = calendarmodel
# if precision is given it overwrites the autodetection above
@@ -1014,9 +1012,8 @@
:param label: Label describing the data type in error messages.
"""
if not isinstance(page, Page):
- raise ValueError(
- 'Page {} must be a pywikibot.Page object not a {}.'
- .format(page, type(page)))
+ raise ValueError(f'Page {page} must be a pywikibot.Page object '
+ f'not a {type(page)}.')
# validate page exists
if not page.exists():
@@ -1304,8 +1301,7 @@
fam = fam or _config.family
if not (code and fam):
- raise ValueError('Missing Site {}'
- .format('code' if not code else 'family'))
+ raise ValueError(f"Missing Site {'code' if not code else 'family'}")
if not isinstance(fam, Family):
fam = Family.load(fam)
@@ -1337,8 +1333,7 @@
key = f'{interface.__name__}:{fam}:{code}:{user}'
if key not in _sites or not isinstance(_sites[key], interface):
_sites[key] = interface(code=code, fam=fam, user=user)
- debug("Instantiated {} object '{}'"
- .format(interface.__name__, _sites[key]))
+ debug(f"Instantiated {interface.__name__} object '{_sites[key]}'")
if _sites[key].code != code:
warn('Site {} instantiated using different code "{}"'
diff --git a/pywikibot/bot.py b/pywikibot/bot.py
index 946d2dc..d40f640 100644
--- a/pywikibot/bot.py
+++ b/pywikibot/bot.py
@@ -420,8 +420,8 @@
logfile = config.datafilepath('logs', config.logfilename)
else:
# add PID to logfle name
- logfile = config.datafilepath('logs', '{}-{}bot.log'
- .format(module_name, pid))
+ logfile = config.datafilepath('logs',
+ f'{module_name}-{pid}bot.log')
# give up infinite rotating file handler with logfilecount of -1;
# set it to 999 and use the standard implementation
@@ -473,8 +473,8 @@
This may help the user to track errors or report bugs.
"""
log('')
- log('=== Pywikibot framework v{} -- Logging header ==='
- .format(pywikibot.__version__))
+ log(f'=== Pywikibot framework v{pywikibot.__version__} -- Logging header'
+ ' ===')
# script call
log(f'COMMAND: {sys.argv}')
@@ -511,7 +511,7 @@
for name in sorted(packages.keys()):
info = packages[name]
info.setdefault('path',
- '[{}]'.format(info.get('type', 'path unknown')))
+ f"[{info.get('type', 'path unknown')}]")
info.setdefault('ver', '??')
if 'err' in info:
log(' {name}: {err}'.format_map(info))
@@ -797,12 +797,11 @@
# at the beginning of the link, start red color.
# at the end of the link, reset the color to default
pywikibot.info(text[max(0, rng[0] - self.context): rng[0]]
- + '<<lightred>>{}<<default>>'.format(
- text[rng[0]: rng[1]])
+ + f'<<lightred>>{text[rng[0]:rng[1]]}<<default>>'
+ text[rng[1]: rng[1] + self.context])
else:
- question += '<<lightred>>{}<<default>> '.format(
- self._old.canonical_title())
+ question += (
+ f'<<lightred>>{self._old.canonical_title()}<<default>> ')
if self._new is False:
question += 'be unlinked?'
@@ -947,8 +946,8 @@
elif option in ('-cosmeticchanges', '-cc'):
config.cosmetic_changes = (strtobool(value) if value
else not config.cosmetic_changes)
- output('NOTE: option cosmetic_changes is {}\n'
- .format(config.cosmetic_changes))
+ output(f'NOTE: option cosmetic_changes is '
+ f'{config.cosmetic_changes}\n')
elif option == '-simulate':
config.simulate = value or True
#
@@ -1158,8 +1157,7 @@
super().__init__(options)
def __missing__(self, key: str) -> None:
- raise Error("'{}' is not a valid option for {}."
- .format(key, self._classname))
+ raise Error(f"'{key}' is not a valid option for {self._classname}.")
def __getattr__(self, name: str) -> Any:
"""Get item from dict."""
@@ -1242,8 +1240,7 @@
self.opt.update((opt, options[opt])
for opt in received_options & valid_options)
for opt in received_options - valid_options:
- pywikibot.warning('{} is not a valid option. It was ignored.'
- .format(opt))
+ pywikibot.warning(f'{opt} is not a valid option. It was ignored.')
class BaseBot(OptionHandler):
@@ -1385,8 +1382,7 @@
msg = f'Working on {page.title()!r}'
if config.colorized_output:
log(msg)
- stdout('\n\n>>> <<lightpurple>>{}<<default>> <<<'
- .format(page.title()))
+ stdout(f'\n\n>>> <<lightpurple>>{page.title()}<<default>> <<<')
else:
stdout(msg)
@@ -1445,7 +1441,7 @@
pywikibot.showDiff(oldtext, newtext)
if 'summary' in kwargs:
- pywikibot.info('Edit summary: {}'.format(kwargs['summary']))
+ pywikibot.info(f"Edit summary: {kwargs['summary']}")
page.text = newtext
return self._save_page(page, page.save, **kwargs)
@@ -1489,22 +1485,21 @@
if not ignore_save_related_errors:
raise
if isinstance(e, EditConflictError):
- pywikibot.info('Skipping {} because of edit conflict'
- .format(page.title()))
+ pywikibot.info(
+ f'Skipping {page.title()} because of edit conflict')
elif isinstance(e, SpamblacklistError):
pywikibot.info('Cannot change {} because of blacklist '
'entry {}'.format(page.title(), e.url))
elif isinstance(e, LockedPageError):
- pywikibot.info('Skipping {} (locked page)'
- .format(page.title()))
+ pywikibot.info(f'Skipping {page.title()} (locked page)')
else:
pywikibot.error('Skipping {} because of a save related '
'error: {}'.format(page.title(), e))
except ServerError as e:
if not ignore_server_errors:
raise
- pywikibot.error('Server Error while processing {}: {}'
- .format(page.title(), e))
+ pywikibot.error(
+ f'Server Error while processing {page.title()}: {e}')
else:
return True
return False
@@ -1536,8 +1531,7 @@
pywikibot.info()
for op, count in self.counter.items():
- pywikibot.info('{} {} operation{}'
- .format(count, op, 's' if count > 1 else ''))
+ pywikibot.info(f"{count} {op} operation{'s' if count > 1 else ''}")
if hasattr(self, '_start_ts'):
write_delta = pywikibot.Timestamp.now() - self._start_ts
@@ -1678,8 +1672,7 @@
self.generator_completed = True
except QuitKeyboardInterrupt:
- pywikibot.info('\nUser quit {} bot run...'
- .format(self.__class__.__name__))
+ pywikibot.info(f'\nUser quit {self.__class__.__name__} bot run...')
except KeyboardInterrupt:
if config.verbose_output:
raise
@@ -1817,8 +1810,8 @@
if self._site == value:
pywikibot.warning('Defined site without changing it.')
else:
- pywikibot.warning('Changed the site from "{}" to '
- '"{}"'.format(self._site, value))
+ pywikibot.warning(
+ f'Changed the site from "{self._site}" to "{value}"')
self._site = value
def init_page(self, item: Any) -> 'pywikibot.page.BasePage':
@@ -2206,7 +2199,7 @@
pywikibot.info(json.dumps(diff, indent=4, sort_keys=True))
if 'summary' in kwargs:
- pywikibot.info('Change summary: {}'.format(kwargs['summary']))
+ pywikibot.info(f"Change summary: {kwargs['summary']}")
# TODO PageSaveRelatedErrors should be actually raised in editEntity
# (bug T86083)
@@ -2245,8 +2238,7 @@
if sourceclaim:
claim.addSource(sourceclaim)
- pywikibot.info('Adding {} --> {}'.format(claim.getID(),
- claim.getTarget()))
+ pywikibot.info(f'Adding {claim.getID()} --> {claim.getTarget()}')
return self._save_page(item, item.addClaim, claim, bot=bot, **kwargs)
def getSource(self, site: 'BaseSite') -> Optional['pywikibot.page.Claim']:
diff --git a/pywikibot/bot_choice.py b/pywikibot/bot_choice.py
index b322367..18c00a5 100644
--- a/pywikibot/bot_choice.py
+++ b/pywikibot/bot_choice.py
@@ -58,7 +58,7 @@
for option in options:
formatted_options.append(option.format(default=default))
# remove color highlights before fill function
- text = '{} ({})'.format(text, ', '.join(formatted_options))
+ text = f"{text} ({', '.join(formatted_options)})"
pattern = '<<[a-z]+>>'
highlights = re.findall(pattern, text)
return fill(re.sub(pattern, '{}', text), width=77).format(*highlights)
diff --git a/pywikibot/comms/eventstreams.py b/pywikibot/comms/eventstreams.py
index 7f07bc0..66cba5f 100644
--- a/pywikibot/comms/eventstreams.py
+++ b/pywikibot/comms/eventstreams.py
@@ -338,8 +338,8 @@
try:
event = next(self.source)
except (ProtocolError, OSError, httplib.IncompleteRead) as e:
- warning('Connection error: {}.\n'
- 'Try to re-establish connection.'.format(e))
+ warning(
+ f'Connection error: {e}.\nTry to re-establish connection.')
del self.source
if event is not None:
self.sse_kwargs['last_id'] = event.id
@@ -349,8 +349,7 @@
try:
element = json.loads(event.data)
except ValueError as e:
- warning('Could not load json data from\n{}\n{}'
- .format(event, e))
+ warning(f'Could not load json data from\n{event}\n{e}')
else:
if self.streamfilter(element):
n += 1
diff --git a/pywikibot/comms/http.py b/pywikibot/comms/http.py
index 8fed6a6..5ef5f3a 100644
--- a/pywikibot/comms/http.py
+++ b/pywikibot/comms/http.py
@@ -348,8 +348,8 @@
raise Client414Error(HTTPStatus(response.status_code).description)
if response.status_code == HTTPStatus.GATEWAY_TIMEOUT:
- raise Server504Error('Server {} timed out'
- .format(urlparse(response.url).netloc))
+ raise Server504Error(
+ f'Server {urlparse(response.url).netloc} timed out')
if (not response.ok
and response.status_code >= HTTPStatus.INTERNAL_SERVER_ERROR):
@@ -436,8 +436,7 @@
if auth is not None and len(auth) == 4:
if isinstance(requests_oauthlib, ImportError):
warn(str(requests_oauthlib), ImportWarning)
- error('OAuth authentication not supported: {}'
- .format(requests_oauthlib))
+ error(f'OAuth authentication not supported: {requests_oauthlib}')
auth = None
else:
auth = requests_oauthlib.OAuth1(*auth)
@@ -532,8 +531,7 @@
try:
content.decode(encoding)
except LookupError:
- pywikibot.warning('Unknown or invalid encoding {!r}'
- .format(encoding))
+ pywikibot.warning(f'Unknown or invalid encoding {encoding!r}')
except UnicodeDecodeError as e:
pywikibot.warning(f'{e} found in {content}')
else:
diff --git a/pywikibot/config.py b/pywikibot/config.py
index c261267..e26387d 100644
--- a/pywikibot/config.py
+++ b/pywikibot/config.py
@@ -34,7 +34,7 @@
default. Editor detection functions were moved to :mod:`editor`.
"""
#
-# (C) Pywikibot team, 2003-2022
+# (C) Pywikibot team, 2003-2023
#
# Distributed under the terms of the MIT license.
#
@@ -369,8 +369,8 @@
elif win_version in (6, 10):
sub_dir = ['AppData', 'Roaming']
else:
- raise OSError('Windows version {} not supported yet.'
- .format(win_version))
+ raise OSError(
+ f'Windows version {win_version} not supported yet.')
base_dir_cand.extend([[home] + sub_dir + ['Pywikibot'],
[home] + sub_dir + ['pywikibot']])
else:
@@ -452,8 +452,8 @@
if not os.path.exists(folder_path):
if not_exists_ok:
return
- raise FileNotFoundError('Family folder {!r} does not exist'
- .format(folder_path))
+ raise FileNotFoundError(
+ f'Family folder {folder_path!r} does not exist')
if os.path.isdir(folder_path):
for file_name in os.listdir(folder_path):
diff --git a/pywikibot/data/api/_generators.py b/pywikibot/data/api/_generators.py
index 8164754..1a30567 100644
--- a/pywikibot/data/api/_generators.py
+++ b/pywikibot/data/api/_generators.py
@@ -6,7 +6,7 @@
:class:`tools.collections.GeneratorWrapper`
"""
#
-# (C) Pywikibot team, 2008-2022
+# (C) Pywikibot team, 2008-2023
#
# Distributed under the terms of the MIT license.
#
@@ -157,13 +157,12 @@
n = 0
while True:
self.request[self.continue_name] = offset
- pywikibot.debug('{}: Request: {}'
- .format(type(self).__name__, self.request))
+ pywikibot.debug(f'{type(self).__name__}: Request: {self.request}')
data = self.request.submit()
n_items = len(data[self.data_name])
- pywikibot.debug('{}: Retrieved {} items'
- .format(type(self).__name__, n_items))
+ pywikibot.debug(
+ f'{type(self).__name__}: Retrieved {n_items} items')
if n_items > 0:
for item in data[self.data_name]:
yield item
@@ -561,9 +560,8 @@
else:
resultdata = [resultdata[k]
for k in sorted(resultdata)]
- pywikibot.debug('{name} received {keys}; limit={limit}'
- .format(name=type(self).__name__, keys=keys,
- limit=self.limit))
+ pywikibot.debug(
+ f'{type(self).__name__} received {keys}; limit={self.limit}')
return resultdata
def _extract_results(self, resultdata):
@@ -811,9 +809,8 @@
elif isinstance(v, list):
old_dict.setdefault(k, []).extend(v)
else:
- raise ValueError(
- 'continued API result had an unexpected type: {}'
- .format(type(v).__name__))
+ raise ValueError(f'continued API result had an unexpected '
+ f'type: {type(v).__name__}')
class ListGenerator(QueryGenerator):
@@ -878,13 +875,11 @@
# Something is wrong.
if page.site.sametitle(page.title(), pagedict['title']) \
and 'invalid' in pagedict:
- raise InvalidTitleError('{}: {}'
- .format(page, pagedict['invalidreason']))
+ raise InvalidTitleError(f"{page}: {pagedict['invalidreason']}")
if int(pagedict['ns']) < 0:
raise UnsupportedPageError(page)
- raise RuntimeError(
- "Page {} has neither 'pageid' nor 'missing' attribute"
- .format(pagedict['title']))
+ raise RuntimeError(f"Page {pagedict['title']} has neither 'pageid'"
+ " nor 'missing' attribute")
def _update_contentmodel(page, pagedict: dict) -> None:
@@ -1003,8 +998,7 @@
if 'imageinfo' in pagedict:
if not isinstance(page, pywikibot.FilePage):
raise RuntimeError(
- '"imageinfo" found but {} is not a FilePage object'
- .format(page))
+ f'"imageinfo" found but {page} is not a FilePage object')
page._load_file_revisions(pagedict['imageinfo'])
if 'categoryinfo' in pagedict:
diff --git a/pywikibot/data/api/_optionset.py b/pywikibot/data/api/_optionset.py
index a947d06..3b91d14 100644
--- a/pywikibot/data/api/_optionset.py
+++ b/pywikibot/data/api/_optionset.py
@@ -113,8 +113,7 @@
elif value is None:
removed.add(name)
else:
- raise ValueError('Dict contains invalid value "{}"'.format(
- value))
+ raise ValueError(f'Dict contains invalid value "{value}"')
invalid_names = (
(enabled - self._valid_enable) | (disabled - self._valid_disable)
| (removed - self._valid_enable - self._valid_disable)
diff --git a/pywikibot/data/api/_paraminfo.py b/pywikibot/data/api/_paraminfo.py
index d2a9cc8..1097c00 100644
--- a/pywikibot/data/api/_paraminfo.py
+++ b/pywikibot/data/api/_paraminfo.py
@@ -400,8 +400,8 @@
if not name and php_class:
name = removeprefix(php_class, 'Api').lower()
if name not in ('main', 'pageset'):
- pywikibot.warning('Unknown paraminfo module "{}"'
- .format(php_class))
+ pywikibot.warning(
+ f'Unknown paraminfo module "{php_class}"')
name = '<unknown>:' + php_class
mod_data['name'] = name
@@ -421,8 +421,7 @@
if path in result_data:
# Only warn first time
if result_data[path] is not False:
- pywikibot.warning('Path "{}" is ambiguous.'
- .format(path))
+ pywikibot.warning(f'Path "{path}" is ambiguous.')
else:
pywikibot.log(f'Found another path "{path}"')
result_data[path] = False
@@ -499,9 +498,8 @@
return None
if len(param_data) != 1:
- raise RuntimeError(
- 'parameter data length is eiter empty or not unique.\n{}'
- .format(param_data))
+ raise RuntimeError(f'parameter data length is eiter empty or not '
+ f'unique.\n{param_data}')
return param_data[0]
@property
diff --git a/pywikibot/data/memento.py b/pywikibot/data/memento.py
index af2c085..ed770fe 100644
--- a/pywikibot/data/memento.py
+++ b/pywikibot/data/memento.py
@@ -287,8 +287,8 @@
allow_redirects=follow_redirects,
timeout=timeout or 9)
except (InvalidSchema, MissingSchema):
- raise ValueError('Only HTTP URIs are supported, '
- 'URI {} unrecognized.'.format(uri))
+ raise ValueError(
+ f'Only HTTP URIs are supported, URI {uri} unrecognized.')
if session_set:
session.close()
diff --git a/pywikibot/data/sparql.py b/pywikibot/data/sparql.py
index 1b3fcc4..5c4e14e 100644
--- a/pywikibot/data/sparql.py
+++ b/pywikibot/data/sparql.py
@@ -1,6 +1,6 @@
"""SPARQL Query interface."""
#
-# (C) Pywikibot team, 2016-2022
+# (C) Pywikibot team, 2016-2023
#
# Distributed under the terms of the MIT license.
#
@@ -67,8 +67,8 @@
'Please provide the endpoint and entity_url '
'parameters instead of a repo.')
if not self.endpoint:
- raise Error('The site {} does not provide a sparql endpoint.'
- .format(repo))
+ raise Error(
+ f'The site {repo} does not provide a sparql endpoint.')
else:
if not entity_url:
raise Error('If initialised with an endpoint the entity_url '
@@ -126,8 +126,7 @@
values[var] = None
elif full_data:
if row[var]['type'] not in VALUE_TYPES:
- raise ValueError('Unknown type: {}'
- .format(row[var]['type']))
+ raise ValueError(f"Unknown type: {row[var]['type']}")
valtype = VALUE_TYPES[row[var]['type']]
values[var] = valtype(row[var],
entity_url=self.entity_url)
diff --git a/pywikibot/date.py b/pywikibot/date.py
index 00a654e..c344cba 100644
--- a/pywikibot/date.py
+++ b/pywikibot/date.py
@@ -499,8 +499,7 @@
for i, param in enumerate(params))
return strPattern % str_params
assert len(decoders) == 1, (
- 'A single parameter does not match {} decoders.'
- .format(len(decoders)))
+ f'A single parameter does not match {len(decoders)} decoders.')
# convert integer parameter into its textual representation
assert isinstance(params, int)
return strPattern % _make_parameter(decoders[0], params)
@@ -690,8 +689,8 @@
self.data[key] = value
def __delitem__(self, key: str) -> None:
- raise NotImplementedError("Deleting of key '{}' is not implemented"
- .format(key))
+ raise NotImplementedError(
+ f"Deleting of key '{key}' is not implemented")
def __iter__(self) -> Iterator[str]:
return iter(self.data)
@@ -1675,7 +1674,7 @@
:param lang: language code
"""
- assert len(patterns) == 12, 'pattern %s does not have 12 elements' % lang
+ assert len(patterns) == 12, f'pattern {lang} does not have 12 elements'
for i in range(12):
if patterns[i] is not None:
@@ -1989,8 +1988,7 @@
max_day = calendar.monthrange(year, month)[1]
if not 1 <= day <= max_day:
raise ValueError(
- 'Wrong day value {day}; must be 1-{max_day}'
- .format(day=day, max_day=max_day))
+ f'Wrong day value {day}; must be 1-{max_day}')
assert isinstance(lang, str)
return formats[dayMnthFmts[month - 1]][lang](day)
diff --git a/pywikibot/diff.py b/pywikibot/diff.py
index fa99103..7e3f78a 100644
--- a/pywikibot/diff.py
+++ b/pywikibot/diff.py
@@ -1,6 +1,6 @@
"""Diff module."""
#
-# (C) Pywikibot team, 2014-2022
+# (C) Pywikibot team, 2014-2023
#
# Distributed under the terms of the MIT license.
#
@@ -168,8 +168,7 @@
if line_ref is None:
if color in self.colors:
- colored_line = '<<{color}>>{}<<default>>'.format(
- line, color=self.colors[color])
+ colored_line = f'<<{self.colors[color]}>>{line}<<default>>'
return colored_line
return line
@@ -185,8 +184,7 @@
apply_color = self.colors[color]
else:
apply_color = 'default;' + self.bg_colors[color]
- char_tagged = '<<{color}>>{}'.format(char,
- color=apply_color)
+ char_tagged = f'<<{apply_color}>>{char}'
color_closed = False
else:
if char_ref == ' ':
@@ -442,8 +440,8 @@
answers.append('?')
pywikibot.info(self._generate_diff(super_hunk))
- choice = pywikibot.input('Accept this hunk [{}]?'.format(
- ','.join(answers)))
+ choice = pywikibot.input(
+ f"Accept this hunk [{','.join(answers)}]?")
if choice not in answers:
choice = '?'
diff --git a/pywikibot/exceptions.py b/pywikibot/exceptions.py
index e5c1a6a..9b90924 100644
--- a/pywikibot/exceptions.py
+++ b/pywikibot/exceptions.py
@@ -697,8 +697,8 @@
:param entity: Wikibase entity
"""
- super().__init__("Entity '{}' doesn't exist on {}"
- .format(entity.id, entity.repo))
+ super().__init__(
+ f"Entity '{entity.id}' doesn't exist on {entity.repo}")
self.entity = entity
diff --git a/pywikibot/family.py b/pywikibot/family.py
index ed75706..0c87877 100644
--- a/pywikibot/family.py
+++ b/pywikibot/family.py
@@ -328,12 +328,10 @@
raise UnknownFamilyError(f'Family {fam} does not exist')
cls = mod.Family.instance
if cls.name != fam:
- warnings.warn(
- 'Family name {} does not match family module name {}'
- .format(cls.name, fam),
- FamilyMaintenanceWarning,
- stacklevel=2,
- )
+ warnings.warn(f'Family name {cls.name} does not match family '
+ f'module name {fam}',
+ FamilyMaintenanceWarning,
+ stacklevel=2)
# Family 'name' and the 'langs' codes must be ascii letters and digits,
# and codes must be lower-case due to the Site loading algorithm;
# codes can accept also underscore/dash.
@@ -423,8 +421,7 @@
return self.disambiguationTemplates[fallback]
raise KeyError(
- 'ERROR: title for disambig template in language {} unknown'
- .format(code))
+ f'ERROR: title for disambig template in language {code} unknown')
# Methods
def protocol(self, code: str) -> str:
@@ -543,8 +540,7 @@
"""Return interface to use for code."""
if code in self.interwiki_removals:
if code in self.codes:
- pywikibot.warn('Interwiki removal {} is in {} codes'
- .format(code, self))
+ pywikibot.warn(f'Interwiki removal {code} is in {self} codes')
if code in self.closed_wikis:
return 'ClosedSite'
if code in self.removed_wikis:
@@ -804,8 +800,7 @@
if cls.languages_by_size:
return cls.languages_by_size
raise NotImplementedError(
- 'Family {} needs property "languages_by_size" or "codes"'
- .format(cls.name))
+ f'Family {cls.name} needs property "languages_by_size" or "codes"')
@classproperty
def domains(cls):
diff --git a/pywikibot/i18n.py b/pywikibot/i18n.py
index 3f1da0b..f14d4e7 100644
--- a/pywikibot/i18n.py
+++ b/pywikibot/i18n.py
@@ -483,8 +483,7 @@
specific_entries[int(number)] = plural
else:
assert not specific_entries, (
- 'generic entries defined after specific in "{}"'
- .format(variants))
+ f'generic entries defined after specific in "{variants}"')
plural_entries.append(plural)
if num in specific_entries:
@@ -625,8 +624,8 @@
break
else:
if fallback is not False:
- raise KeyError('No fallback key found in lookup dict for "{}"'
- .format(code))
+ raise KeyError(
+ f'No fallback key found in lookup dict for "{code}"')
trans = None
if trans is None:
diff --git a/pywikibot/interwiki_graph.py b/pywikibot/interwiki_graph.py
index 96cd28b..041e9d7 100644
--- a/pywikibot/interwiki_graph.py
+++ b/pywikibot/interwiki_graph.py
@@ -162,8 +162,7 @@
# https://sourceforge.net/p/pywikipediabot/bugs/401/
elif self.graph.get_edge(sourceLabel, targetLabel):
pywikibot.error(
- 'Tried to create duplicate edge from {} to {}'
- .format(refPage, page))
+ f'Tried to create duplicate edge from {refPage} to {page}')
# duplicate edges would be bad because then get_edge() would
# give a list of edges, not a single edge when we handle the
# opposite edge.
@@ -194,8 +193,7 @@
For more info see https://meta.wikimedia.org/wiki/Interwiki_graphs
"""
- pywikibot.info('Preparing graph for {}'
- .format(self.subject.origin.title()))
+ pywikibot.info(f'Preparing graph for {self.subject.origin.title()}')
# create empty graph
self.graph = pydot.Dot()
diff --git a/pywikibot/logentries.py b/pywikibot/logentries.py
index 00aed03..33dcc3c 100644
--- a/pywikibot/logentries.py
+++ b/pywikibot/logentries.py
@@ -1,6 +1,6 @@
"""Objects representing Mediawiki log entries."""
#
-# (C) Pywikibot team, 2007-2022
+# (C) Pywikibot team, 2007-2023
#
# Distributed under the terms of the MIT license.
#
@@ -64,13 +64,12 @@
"permission to view it due to '{}'"
.format(self['type'], key, hidden_key))
- raise KeyError('Log entry ({}) has no {!r} key'
- .format(self['type'], key))
+ raise KeyError(f"Log entry ({self['type']}) has no {key!r} key")
def __repr__(self) -> str:
"""Return a string representation of LogEntry object."""
- return '<{}({}, logid={})>'.format(type(self).__name__,
- self.site.sitename, self.logid())
+ return (f'<{type(self).__name__}({self.site.sitename}, '
+ f'logid={self.logid()})>')
def __hash__(self) -> int:
"""Combine site and logid as the hash."""
diff --git a/pywikibot/login.py b/pywikibot/login.py
index 97d6dbc..54c57ee 100644
--- a/pywikibot/login.py
+++ b/pywikibot/login.py
@@ -378,9 +378,8 @@
if hasattr(self, '_waituntil') \
and datetime.datetime.now() < self._waituntil:
diff = self._waituntil - datetime.datetime.now()
- pywikibot.warning(
- 'Too many tries, waiting {} seconds before retrying.'
- .format(diff.seconds))
+ pywikibot.warning(f'Too many tries, waiting {diff.seconds}'
+ ' seconds before retrying.')
pywikibot.sleep(diff.seconds)
self.site._loginstatus = LoginStatus.IN_PROGRESS
diff --git a/pywikibot/page/_basepage.py b/pywikibot/page/_basepage.py
index 8a7374e..7c62214 100644
--- a/pywikibot/page/_basepage.py
+++ b/pywikibot/page/_basepage.py
@@ -1324,8 +1324,8 @@
return summary
old = self.text
- pywikibot.log('Cosmetic changes for {}-{} enabled.'
- .format(family, self.site.lang))
+ pywikibot.log(
+ f'Cosmetic changes for {family}-{self.site.lang} enabled.')
# cc depends on page directly and via several other imports
cc_toolkit = CosmeticChangesToolkit(self, ignore=CANCEL.MATCH)
self.text = cc_toolkit.change(old)
@@ -1896,8 +1896,8 @@
answer = 'y'
else:
answer = pywikibot.input_choice(
- "Can't delete {}; do you want to mark it for deletion instead?"
- .format(self),
+ f"Can't delete {self};"
+ ' do you want to mark it for deletion instead?',
[('Yes', 'y'), ('No', 'n'), ('All', 'a')],
'n', automatic_quit=False)
if answer == 'a':
@@ -1980,8 +1980,7 @@
self.loadDeletedRevisions()
if timestamp not in self._deletedRevs:
raise ValueError(
- 'Timestamp {} is not a deleted revision'
- .format(timestamp))
+ f'Timestamp {timestamp} is not a deleted revision')
self._deletedRevs[timestamp]['marked'] = undelete
def undelete(self, reason: Optional[str] = None) -> None:
@@ -2106,8 +2105,8 @@
if old_cat not in cats:
if self.namespace() != 10:
- pywikibot.error('{} is not in category {}!'
- .format(self, old_cat.title()))
+ pywikibot.error(
+ f'{self} is not in category {old_cat.title()}!')
else:
pywikibot.info('{} is not in category {}, skipping...'
.format(self, old_cat.title()))
diff --git a/pywikibot/page/_category.py b/pywikibot/page/_category.py
index fb42b80..87313a5 100644
--- a/pywikibot/page/_category.py
+++ b/pywikibot/page/_category.py
@@ -1,6 +1,6 @@
"""Object representing a MediaWiki category page."""
#
-# (C) Pywikibot team, 2008-2022
+# (C) Pywikibot team, 2008-2023
#
# Distributed under the terms of the MIT license.
#
@@ -28,8 +28,8 @@
self.sortKey = sort_key
super().__init__(source, title, ns=14)
if self.namespace() != 14:
- raise ValueError("'{}' is not in the category namespace!"
- .format(self.title()))
+ raise ValueError(
+ f"'{self.title()}' is not in the category namespace!")
def aslink(self, sort_key: Optional[str] = None) -> str:
"""Return a link to place a page in this Category.
diff --git a/pywikibot/page/_collections.py b/pywikibot/page/_collections.py
index 77d8ad8..6f40b30 100644
--- a/pywikibot/page/_collections.py
+++ b/pywikibot/page/_collections.py
@@ -525,8 +525,7 @@
try:
index = self._by_key[index]
except KeyError as e:
- raise ValueError('No entity with id {} was found'
- .format(index)) from e
+ raise ValueError(f'No entity with id {index} was found') from e
return self._data[index]
def __setitem__(self, index, value):
@@ -537,8 +536,7 @@
try:
index = self._by_key[index]
except KeyError as e:
- raise ValueError('No entity with id {} was found'
- .format(index)) from e
+ raise ValueError(f'No entity with id {index} was found') from e
obj = self._data[index]
del self._data[index]
del self._by_key[obj.id]
diff --git a/pywikibot/page/_decorators.py b/pywikibot/page/_decorators.py
index ad3a32a..2e90b5d 100644
--- a/pywikibot/page/_decorators.py
+++ b/pywikibot/page/_decorators.py
@@ -37,8 +37,7 @@
err = edit_err # edit_err will be deleted in the end of the scope
link = self.title(as_link=True)
if do_async:
- pywikibot.error('page {} not saved due to {}\n'
- .format(link, err))
+ pywikibot.error(f'page {link} not saved due to {err}\n')
pywikibot.log(f'Error saving page {link} ({err})\n',
exc_info=True)
if not callback and not do_async:
diff --git a/pywikibot/page/_filepage.py b/pywikibot/page/_filepage.py
index a6c6473..2317fac 100644
--- a/pywikibot/page/_filepage.py
+++ b/pywikibot/page/_filepage.py
@@ -43,16 +43,15 @@
self._file_revisions = {} # dictionary to cache File history.
super().__init__(source, title, 6)
if self.namespace() != 6:
- raise ValueError("'{}' is not in the file namespace!"
- .format(self.title()))
+ raise ValueError(f"'{self.title()}' is not in the file namespace!")
def _load_file_revisions(self, imageinfo) -> None:
for file_rev in imageinfo:
# filemissing in API response indicates most fields are missing
# see https://gerrit.wikimedia.org/r/c/mediawiki/core/+/533482/
if 'filemissing' in file_rev:
- pywikibot.warning("File '{}' contains missing revisions"
- .format(self.title()))
+ pywikibot.warning(
+ f"File '{self.title()}' contains missing revisions")
continue
file_revision = FileInfo(file_rev)
self._file_revisions[file_revision.timestamp] = file_revision
diff --git a/pywikibot/page/_links.py b/pywikibot/page/_links.py
index 36ba716..fb156b8 100644
--- a/pywikibot/page/_links.py
+++ b/pywikibot/page/_links.py
@@ -6,7 +6,7 @@
its contents.
"""
#
-# (C) Pywikibot team, 2008-2022
+# (C) Pywikibot team, 2008-2023
#
# Distributed under the terms of the MIT license.
#
@@ -80,8 +80,7 @@
assert all(isinstance(item, str) for item in self._items)
attrs = (f'{getattr(self, attr)!r}' for attr in self._items)
- return 'pywikibot.page.{}({})'.format(type(self).__name__,
- ', '.join(attrs))
+ return f"pywikibot.page.{type(self).__name__}({', '.join(attrs)})"
def lookup_namespace(self):
"""
@@ -105,9 +104,8 @@
ns = self.site.namespaces[default_nskey]
return ns
- raise TypeError(
- 'Invalid type "{}" for Page._nskey. Must be int or str.'
- .format(type(self._nskey)))
+ raise TypeError(f'Invalid type "{type(self._nskey)}" for Page._nskey.'
+ ' Must be int or str.')
@property
def site(self):
@@ -135,8 +133,7 @@
"""Return full page title, including localized namespace."""
# Avoid that ':' will be added to the title for Main ns.
if self.namespace != Namespace.MAIN:
- return '{}:{}'.format(self.site.namespace(self.namespace),
- self.title)
+ return f'{self.site.namespace(self.namespace)}:{self.title}'
return self.title
def ns_title(self, onsite=None):
@@ -454,8 +451,7 @@
# Reject illegal characters.
m = Link.illegal_titles_pattern.search(t)
if m:
- raise InvalidTitleError('{!r} contains illegal char(s) {!r}'
- .format(t, m.group(0)))
+ raise InvalidTitleError(f'{t!r} contains illegal char(s) {m[0]!r}')
# Pages with "/./" or "/../" appearing in the URLs will
# often be unreachable due to the way web browsers deal
@@ -467,13 +463,11 @@
or '/../' in t
or t.endswith(('/.', '/..'))):
raise InvalidTitleError(
- "(contains . / combinations): '{}'"
- .format(self._text))
+ f"(contains . / combinations): '{self._text}'")
# Magic tilde sequences? Nu-uh!
if '~~~' in t:
- raise InvalidTitleError("(contains ~~~): '{}'"
- .format(self._text))
+ raise InvalidTitleError(f"(contains ~~~): '{self._text}'")
if self._namespace != -1 and len(t) > 255:
raise InvalidTitleError(f"(over 255 bytes): '{t}'")
@@ -482,8 +476,7 @@
# with a fragment identifier.
if not t.strip(' ') and not self._is_interwiki: # T197642
raise InvalidTitleError(
- 'The link [[{}]] does not contain a page title'
- .format(self._text))
+ f'The link [[{self._text}]] does not contain a page title')
# MediaWiki uses uppercase IP addresses
if self._namespace in (2, 3) and is_ip_address(t):
@@ -550,7 +543,7 @@
onsite = self._source
text = super().astext(onsite)
if self.section:
- text = '{}#{}]]'.format(text.rstrip(']'), self.section)
+ text = f"{text.rstrip(']')}#{self.section}]]"
return text
diff --git a/pywikibot/page/_user.py b/pywikibot/page/_user.py
index c889dba..31c62d4 100644
--- a/pywikibot/page/_user.py
+++ b/pywikibot/page/_user.py
@@ -46,8 +46,7 @@
self._isAutoblock = False
super().__init__(source, title, ns=2)
if self.namespace() != 2:
- raise ValueError("'{}' is not in the user namespace!"
- .format(self.title()))
+ raise ValueError(f"'{self.title()}' is not in the user namespace!")
if self._isAutoblock:
# This user is probably being queried for purpose of lifting
# an autoblock.
@@ -275,8 +274,7 @@
self.site.blockuser(self, *args, **kwargs)
except APIError as err:
if err.code == 'invalidrange':
- raise ValueError('{} is not a valid IP range.'
- .format(self.username))
+ raise ValueError(f'{self.username} is not a valid IP range.')
raise err
diff --git a/pywikibot/page/_wikibase.py b/pywikibot/page/_wikibase.py
index 2083a3c..b3a347b 100644
--- a/pywikibot/page/_wikibase.py
+++ b/pywikibot/page/_wikibase.py
@@ -105,15 +105,13 @@
self.id = id_ if id_ is not None else '-1'
if self.id != '-1' and not self.is_valid_id(self.id):
raise InvalidTitleError(
- "'{}' is not a valid {} page title"
- .format(self.id, self.entity_type))
+ f"'{self.id}' is not a valid {self.entity_type} page title")
def __repr__(self) -> str:
if self.id != '-1':
return 'pywikibot.page.{}({!r}, {!r})'.format(
self.__class__.__name__, self.repo, self.id)
- return 'pywikibot.page.{}({!r})'.format(
- self.__class__.__name__, self.repo)
+ return f'pywikibot.page.{self.__class__.__name__}({self.repo!r})'
@classmethod
def is_valid_id(cls, entity_id: str) -> bool:
@@ -393,16 +391,14 @@
# state which needs to be raised as an exception, but also
# logged in case an exception handler is catching
# the generic Error
- pywikibot.error('{} is in invalid state'
- .format(self.__class__.__name__))
- raise Error('{} is in invalid state'
- .format(self.__class__.__name__))
+ msg = f'{self.__class__.__name__} is in invalid state'
+ pywikibot.error(msg)
+ raise Error(msg)
page_id = self.getID(numeric=True)
result = list(self.repo.load_pages_from_pageids([page_id]))
if not result:
- raise Error('There is no existing page with id "{}"'
- .format(page_id))
+ raise Error(f'There is no existing page with id "{page_id}"')
page = result.pop()
if page.namespace() != page.site.namespaces.FILE:
@@ -501,8 +497,8 @@
elif site.property_namespace.id == ns:
self._namespace = site.property_namespace
else:
- raise ValueError('{!r}: Namespace "{}" is not valid'
- .format(site, int(ns)))
+ raise ValueError(
+ f'{site!r}: Namespace "{int(ns)}" is not valid')
if 'entity_type' in kwargs:
entity_type = kwargs.pop('entity_type')
@@ -510,8 +506,8 @@
entity_type_ns = site.get_namespace_for_entity_type(
entity_type)
except EntityTypeUnknownError:
- raise ValueError('Wikibase entity type "{}" unknown'
- .format(entity_type))
+ raise ValueError(
+ f'Wikibase entity type "{entity_type}" unknown')
if self._namespace:
if self._namespace != entity_type_ns:
@@ -543,8 +539,8 @@
elif self.site.property_namespace.id == ns:
self._namespace = self.site.property_namespace
else:
- raise ValueError('{!r}: Namespace "{!r}" is not valid'
- .format(self.site, ns))
+ raise ValueError(
+ f'{self.site!r}: Namespace "{ns!r}" is not valid')
WikibaseEntity.__init__(
self,
@@ -889,10 +885,8 @@
# if none of the above applies, this item is in an invalid state
# which needs to be raise as an exception, but also logged in case
# an exception handler is catching the generic Error.
- pywikibot.error('{} is in invalid state'
- .format(self.__class__.__name__))
- raise Error('{} is in invalid state'
- .format(self.__class__.__name__))
+ pywikibot.error(f'{self.__class__.__name__} is in invalid state')
+ raise Error(f'{self.__class__.__name__} is in invalid state')
return params
@@ -960,8 +954,7 @@
if hasattr(page, '_item'):
return page._item
if not page.site.has_data_repository:
- raise WikiBaseError('{} has no data repository'
- .format(page.site))
+ raise WikiBaseError(f'{page.site} has no data repository')
if not lazy_load and not page.exists():
raise NoPageError(page)
@@ -1709,8 +1702,7 @@
"""
value_class = self.types[self.type]
if not isinstance(value, value_class):
- raise ValueError('{} is not type {}.'
- .format(value, value_class))
+ raise ValueError(f'{value} is not type {value_class}.')
self.target = value
def changeTarget(
diff --git a/pywikibot/pagegenerators/_factory.py b/pywikibot/pagegenerators/_factory.py
index d965d26..4a6f5c4 100644
--- a/pywikibot/pagegenerators/_factory.py
+++ b/pywikibot/pagegenerators/_factory.py
@@ -1,6 +1,6 @@
"""GeneratorFactory module wich handles pagegenerators options."""
#
-# (C) Pywikibot team, 2008-2022
+# (C) Pywikibot team, 2008-2023
#
# Distributed under the terms of the MIT license.
#
@@ -328,8 +328,7 @@
# Part before ":" might be interpreted as an interwiki prefix
prefix = category.split(':', 1)[0] # whole word if ":" not present
if prefix not in self.site.namespaces[14]:
- category = '{}:{}'.format(
- self.site.namespace(14), category)
+ category = f'{self.site.namespace(14)}:{category}'
cat = pywikibot.Category(pywikibot.Link(category,
source=self.site,
default_namespace=14))
@@ -835,8 +834,8 @@
'{}: {}'.format(*i)
for i in self.site.proofread_levels.items()]
valid_ql = ', '.join(valid_ql_list)
- pywikibot.warning('Acceptable values for -ql are:\n {}'
- .format(valid_ql))
+ pywikibot.warning(
+ f'Acceptable values for -ql are:\n {valid_ql}')
self.qualityfilter_list = int_values
return True
diff --git a/pywikibot/pagegenerators/_filters.py b/pywikibot/pagegenerators/_filters.py
index 59cc30f..57d720c 100644
--- a/pywikibot/pagegenerators/_filters.py
+++ b/pywikibot/pagegenerators/_filters.py
@@ -232,8 +232,7 @@
else:
if show_filtered:
pywikibot.info(
- 'Page {} is a subpage that is too deep. Skipping.'
- .format(page))
+ f'Page {page} is a subpage that is too deep. Skipping.')
class RegexFilter:
diff --git a/pywikibot/pagegenerators/_generators.py b/pywikibot/pagegenerators/_generators.py
index d3c1762..d73f499 100644
--- a/pywikibot/pagegenerators/_generators.py
+++ b/pywikibot/pagegenerators/_generators.py
@@ -458,8 +458,8 @@
user = pywikibot.User(site, username)
if not (user.isAnonymous() or user.isRegistered()):
- pywikibot.warning('User "{}" does not exist on site "{}".'
- .format(user.username, site))
+ pywikibot.warning(
+ f'User "{user.username}" does not exist on site "{site}".')
gen = (contrib[0] for contrib in user.contributions(
namespaces=namespaces, total=total))
@@ -875,8 +875,7 @@
"""
# restrict query to local site
local_query = f'{self.query} site:{self.site.hostname()}'
- base = 'http://{}{}'.format(self.site.hostname(),
- self.site.articlepath)
+ base = f'http://{self.site.hostname()}{self.site.articlepath}'
pattern = base.replace('{}', '(.+)')
for url in self.queryGoogle(local_query):
m = re.search(pattern, url)
diff --git a/pywikibot/proofreadpage.py b/pywikibot/proofreadpage.py
index da052e2..8432fc5 100644
--- a/pywikibot/proofreadpage.py
+++ b/pywikibot/proofreadpage.py
@@ -517,8 +517,8 @@
try:
num = int(right)
except ValueError:
- raise InvalidTitleError('{} contains invalid index {!r}'
- .format(self, right))
+ raise InvalidTitleError(
+ f'{self} contains invalid index {right!r}')
else:
base = right
@@ -562,24 +562,22 @@
index_page, others = self._index
if others:
pywikibot.warning(f'{self} linked to several Index pages.')
- pywikibot.info('{}{!s}'.format(' ' * 9, [index_page] + others))
+ pywikibot.info(f"{' ' * 9}{[index_page] + others!s}")
if index_page:
pywikibot.info(
- '{}Selected Index: {}'.format(' ' * 9, index_page))
- pywikibot.info('{}remaining: {!s}'.format(' ' * 9, others))
+ f"{' ' * 9}Selected Index: {index_page}")
+ pywikibot.info(f"{' ' * 9}remaining: {others!s}")
if not index_page:
- pywikibot.warning('Page {} is not linked to any Index page.'
- .format(self))
+ pywikibot.warning(f'Page {self} is not linked to any Index page.')
return index_page
@index.setter
def index(self, value: 'IndexPage') -> None:
if not isinstance(value, IndexPage):
- raise TypeError('value {} must be an IndexPage object.'
- .format(value))
+ raise TypeError(f'value {value} must be an IndexPage object.')
self._index = (value, [])
@index.deleter
@@ -861,8 +859,7 @@
# if None raises TypeError.
url_image = url_image['src']
except (TypeError, AttributeError):
- raise ValueError('No prp-page-image src found for {}.'
- .format(self))
+ raise ValueError(f'No prp-page-image src found for {self}.')
else:
url_image = 'https:' + url_image
@@ -890,8 +887,7 @@
if ocr_tool not in self._OCR_METHODS:
raise TypeError(
- "ocr_tool must be in {}, not '{}'."
- .format(self._OCR_METHODS, ocr_tool))
+ f"ocr_tool must be in {self._OCR_METHODS}, not '{ocr_tool}'.")
# wrong link fail with Exceptions
for retry in range(5, 30, 5):
@@ -983,8 +979,7 @@
cmd_fmt = self._OCR_CMDS[ocr_tool]
except KeyError:
raise TypeError(
- "ocr_tool must be in {}, not '{}'."
- .format(self._OCR_METHODS, ocr_tool))
+ f"ocr_tool must be in {self._OCR_METHODS}, not '{ocr_tool}'.")
params = {
'url_image': url_image,
@@ -1016,16 +1011,15 @@
if ocr_tool not in self._OCR_METHODS:
raise TypeError(
- "ocr_tool must be in {}, not '{}'."
- .format(self._OCR_METHODS, ocr_tool))
+ f"ocr_tool must be in {self._OCR_METHODS}, not '{ocr_tool}'.")
# if _multi_page, try _do_hocr() first and fall back to _do_ocr()
if ocr_tool == self._PHETOOLS and self._multi_page:
error, text = self._do_hocr()
if not error and isinstance(text, str):
return text
- pywikibot.warning('{}: phetools hocr failed, falling back to ocr.'
- .format(self))
+ pywikibot.warning(
+ f'{self}: phetools hocr failed, falling back to ocr.')
error, text = self._do_ocr(ocr_tool=ocr_tool)
@@ -1262,8 +1256,7 @@
# Sanity check if WS site use page convention name/number.
if page._num is not None:
assert page_cnt == int(page._num), (
- 'Page number {} not recognised as page {}.'
- .format(page_cnt, title))
+ f'Page number {page_cnt} not recognised as page {title}.')
# Mapping: numbers <-> pages.
self._page_from_numbers[page_cnt] = page
@@ -1362,8 +1355,7 @@
try:
return self._labels_from_page_number[page_number]
except KeyError:
- raise KeyError('Page number ".../{}" not in range.'
- .format(page_number))
+ raise KeyError(f'Page number ".../{page_number}" not in range.')
@staticmethod
def _get_from_label(mapping_dict: Dict[str, Any],
diff --git a/pywikibot/scripts/generate_family_file.py b/pywikibot/scripts/generate_family_file.py
index 874631b..f6afdd5 100755
--- a/pywikibot/scripts/generate_family_file.py
+++ b/pywikibot/scripts/generate_family_file.py
@@ -257,18 +257,16 @@
sys.exit(1)
code_hostname_pairs = '\n '.join(
- "'{code}': '{hostname}',".format(
- code=k, hostname=urlparse(w.server).netloc
- ) for k, w in self.wikis.items())
+ f"'{k}': '{urlparse(w.server).netloc}',"
+ for k, w in self.wikis.items())
code_path_pairs = '\n '.join(
f"'{k}': '{w.scriptpath}',"
for k, w in self.wikis.items())
code_protocol_pairs = '\n '.join(
- "'{code}': '{protocol}',".format(
- code=k, protocol=urlparse(w.server).scheme
- ) for k, w in self.wikis.items())
+ f"'{k}': '{urlparse(w.server).scheme}',"
+ for k, w in self.wikis.items())
content = family_template % {
'url': self.base_url, 'name': self.name,
diff --git a/pywikibot/scripts/generate_user_files.py b/pywikibot/scripts/generate_user_files.py
index fe5d618..2e25b55 100755
--- a/pywikibot/scripts/generate_user_files.py
+++ b/pywikibot/scripts/generate_user_files.py
@@ -8,7 +8,7 @@
Also EXTERNAL EDITOR SETTINGS section can be copied.
"""
#
-# (C) Pywikibot team, 2010-2022
+# (C) Pywikibot team, 2010-2023
#
# Distributed under the terms of the MIT license.
#
@@ -395,8 +395,8 @@
botpasswordpass))
if not userlist: # Show a sample
- usernames = "# usernames['{}']['{}'] = 'MyUsername'".format(
- main_family, main_code)
+ usernames = (
+ f"# usernames['{main_family}']['{main_code}'] = 'MyUsername'")
else:
usernames = '\n'.join(
"usernames['{user.family}']['{user.code}'] = '{user.name}'"
diff --git a/pywikibot/scripts/preload_sites.py b/pywikibot/scripts/preload_sites.py
index 47a66b6..afda243 100755
--- a/pywikibot/scripts/preload_sites.py
+++ b/pywikibot/scripts/preload_sites.py
@@ -18,7 +18,7 @@
script was moved to the framework scripts folder.
"""
#
-# (C) Pywikibot team, 2021-2022
+# (C) Pywikibot team, 2021-2023
#
# Distributed under the terms of the MIT license.
#
@@ -85,8 +85,8 @@
# to allow adding futures in preload_family the workers must be one
# more than families are handled
worker = max(len(families) * 2, worker)
- pywikibot.info('Using {} workers to process {} families'
- .format(worker, len(families)))
+ pywikibot.info(
+ f'Using {worker} workers to process {len(families)} families')
with ThreadPoolExecutor(worker) as executor:
futures = {executor.submit(preload_family, family, executor)
for family in families}
diff --git a/pywikibot/scripts/shell.py b/pywikibot/scripts/shell.py
index bdfe181..1dafa12 100755
--- a/pywikibot/scripts/shell.py
+++ b/pywikibot/scripts/shell.py
@@ -59,8 +59,7 @@
if sys.platform == 'win32':
import platform
import subprocess
- subprocess.run('title Python {} Shell'
- .format(platform.python_version()),
+ subprocess.run(f'title Python {platform.python_version()} Shell',
shell=True, check=True)
del subprocess
del platform
diff --git a/pywikibot/scripts/version.py b/pywikibot/scripts/version.py
index 12f542d..7a83797 100755
--- a/pywikibot/scripts/version.py
+++ b/pywikibot/scripts/version.py
@@ -63,8 +63,7 @@
or not callable(requests.certs.where)):
pywikibot.info(' cacerts: not defined')
elif not os.path.isfile(requests.certs.where()):
- pywikibot.info(' cacerts: {} (missing)'.format(
- requests.certs.where()))
+ pywikibot.info(f' cacerts: {requests.certs.where()} (missing)')
else:
pywikibot.info(' cacerts: ' + requests.certs.where())
diff --git a/pywikibot/scripts/wrapper.py b/pywikibot/scripts/wrapper.py
index d253be4..cd22f39 100755
--- a/pywikibot/scripts/wrapper.py
+++ b/pywikibot/scripts/wrapper.py
@@ -213,8 +213,7 @@
.format('s' if len(requirements) > 1 else ''))
for requirement in requirements:
- print(' pip install "{}"\n'
- .format(str(requirement).partition(';')[0]))
+ print(f" pip install \"{str(requirement).partition(';')[0]}\"\n")
def check_modules(script=None):
@@ -476,8 +475,8 @@
try:
module = import_module(file_package)
except ImportError as e:
- warn('Parent module {} not found: {}'
- .format(file_package, e), ImportWarning)
+ warn(f'Parent module {file_package} not found: {e}',
+ ImportWarning)
help_option = any(arg.startswith('-help:') or arg == '-help'
for arg in script_args)
diff --git a/pywikibot/site/_basesite.py b/pywikibot/site/_basesite.py
index 97c8d9b..eec692a 100644
--- a/pywikibot/site/_basesite.py
+++ b/pywikibot/site/_basesite.py
@@ -48,12 +48,11 @@
if code.lower() != code:
# Note the Site function in __init__ also emits a UserWarning
# for this condition, showing the callers file and line no.
- pywikibot.log('BaseSite: code "{}" converted to lowercase'
- .format(code))
+ pywikibot.log(f'BaseSite: code "{code}" converted to lowercase')
code = code.lower()
if not all(x in pywikibot.family.CODE_CHARACTERS for x in code):
- pywikibot.log('BaseSite: code "{}" contains invalid characters'
- .format(code))
+ pywikibot.log(
+ f'BaseSite: code "{code}" contains invalid characters')
self.__code = code
if isinstance(fam, str) or fam is None:
self.__family = pywikibot.family.Family.load(fam)
@@ -67,8 +66,8 @@
self.__code = self.__family.obsolete[self.__code]
# Note the Site function in __init__ emits a UserWarning
# for this condition, showing the callers file and line no.
- pywikibot.log('Site {} instantiated using aliases code of {}'
- .format(self, code))
+ pywikibot.log(
+ f'Site {self} instantiated using aliases code of {code}')
else:
# no such language anymore
self.obsolete = True
@@ -209,8 +208,7 @@
def __repr__(self) -> str:
"""Return internal representation."""
- return '{}("{}", "{}")'.format(
- self.__class__.__name__, self.code, self.family)
+ return f'{self.__class__.__name__}("{self.code}", "{self.family}")'
def __hash__(self):
"""Return hash value of instance."""
@@ -321,8 +319,8 @@
else: # fallback for non WM sites
try:
- name = '{}:{}'.format(Namespace.CATEGORY,
- self.family.disambcatname[self.code])
+ name = (f'{Namespace.CATEGORY}:'
+ f'{self.family.disambcatname[self.code]}')
except KeyError:
raise Error(f'No disambiguation category name found in '
f'{self.family.name}_family for {self}')
@@ -375,8 +373,7 @@
# delimiters like spaces and multiple combinations of them with
# only one delimiter
sep = self.family.title_delimiter_and_aliases[0]
- pattern = re.compile('[{}]+'
- .format(self.family.title_delimiter_and_aliases))
+ pattern = re.compile(f'[{self.family.title_delimiter_and_aliases}]+')
title1 = pattern.sub(sep, title1)
title2 = pattern.sub(sep, title2)
if title1 == title2:
diff --git a/pywikibot/site/_datasite.py b/pywikibot/site/_datasite.py
index 119d1eb..e14e4bb 100644
--- a/pywikibot/site/_datasite.py
+++ b/pywikibot/site/_datasite.py
@@ -777,8 +777,8 @@
raise
if 'results' not in data:
- raise RuntimeError("Unexpected missing 'results' in query data\n{}"
- .format(data))
+ raise RuntimeError(
+ f"Unexpected missing 'results' in query data\n{data}")
results = []
for result_hash in data['results']:
diff --git a/pywikibot/site/_extensions.py b/pywikibot/site/_extensions.py
index f252c5d..f6e10e5 100644
--- a/pywikibot/site/_extensions.py
+++ b/pywikibot/site/_extensions.py
@@ -755,7 +755,7 @@
data = req.submit()['query']['pages']
if '-1' in data:
msg = data['-1'].get('invalidreason',
- 'Unknown exception:\n{}'.format(data['-1']))
+ f"Unknown exception:\n{data['-1']}")
raise Error(msg)
return data[str(page.pageid)]['extract']
diff --git a/pywikibot/site/_generators.py b/pywikibot/site/_generators.py
index 04ded77..50b6089 100644
--- a/pywikibot/site/_generators.py
+++ b/pywikibot/site/_generators.py
@@ -1558,8 +1558,7 @@
:param prop: Requested props to check
:raises UserRightsError: user cannot view a requested prop
"""
- err = '{}: User:{} not authorized to view '.format(msg_prefix,
- self.user())
+ err = f'{msg_prefix}: User:{self.user()} not authorized to view '
if not self.has_right('deletedhistory'):
if self.mw_version < '1.34':
raise UserRightsError(err + 'deleted revisions.')
@@ -1901,7 +1900,7 @@
"""
param = self._paraminfo.parameter('query+querypage', 'page')
assert special_page in param['type'], (
- '{} not in {}'.format(special_page, param['type']))
+ f"{special_page} not in {param['type']}")
return self._generator(api.PageGenerator,
type_arg='querypage', gqppage=special_page,
diff --git a/pywikibot/site/_obsoletesites.py b/pywikibot/site/_obsoletesites.py
index cc16046..b5c1223 100644
--- a/pywikibot/site/_obsoletesites.py
+++ b/pywikibot/site/_obsoletesites.py
@@ -21,8 +21,7 @@
def _closed_error(self, notice: str = '') -> None:
"""An error instead of pointless API call."""
- pywikibot.error('Site {} has been closed. {}'.format(self.sitename,
- notice))
+ pywikibot.error(f'Site {self.sitename} has been closed. {notice}')
def page_restrictions(
self, page: 'pywikibot.Page') -> Dict[str, Tuple[str, str]]:
diff --git a/pywikibot/site/_upload.py b/pywikibot/site/_upload.py
index 7239ead..0a0d0b6 100644
--- a/pywikibot/site/_upload.py
+++ b/pywikibot/site/_upload.py
@@ -1,6 +1,6 @@
"""Objects representing API upload to MediaWiki site."""
#
-# (C) Pywikibot team, 2009-2022
+# (C) Pywikibot team, 2009-2023
#
# Distributed under the terms of the MIT license.
#
@@ -181,8 +181,7 @@
if os.path.isfile(self.filename):
file_size = os.path.getsize(self.filename)
elif offset is not False:
- raise ValueError("File '{}' does not exist."
- .format(self.filename))
+ raise ValueError(f"File '{self.filename}' does not exist.")
# Verify the stash when a file key and offset is given:
# requests the SHA1 and file size uploaded and compares it to
@@ -242,8 +241,8 @@
data = {}
if file_key and offset is False or offset == file_size:
- pywikibot.log('Reused already upload file using filekey "{}"'
- .format(file_key))
+ pywikibot.log(
+ f'Reused already upload file using filekey "{file_key}"')
# TODO: Use sessionkey instead of filekey if necessary
final_request = self.site._request(
parameters={
@@ -270,8 +269,7 @@
'filename': file_page_title, 'comment': self.comment})
if chunked_upload:
if offset > 0:
- pywikibot.log('Continuing upload from byte {}'
- .format(offset))
+ pywikibot.log(f'Continuing upload from byte {offset}')
poll = False
while True:
@@ -522,5 +520,5 @@
self.filepage._load_file_revisions([result['imageinfo']])
return True
- raise Error('Unrecognized result: {}'
- .format(data_result or result['result']))
+ raise Error(
+ f"Unrecognized result: {data_result or result['result']}")
diff --git a/pywikibot/specialbots/_upload.py b/pywikibot/specialbots/_upload.py
index a577105..c3f1c7a 100644
--- a/pywikibot/specialbots/_upload.py
+++ b/pywikibot/specialbots/_upload.py
@@ -3,7 +3,7 @@
Do not import classes directly from here but from specialbots.
"""
#
-# (C) Pywikibot team, 2003-2022
+# (C) Pywikibot team, 2003-2023
#
# Distributed under the terms of the MIT license.
#
@@ -158,8 +158,8 @@
# raised from connection lost during response.iter_content()
except requests.ConnectionError:
fd.flush()
- pywikibot.info('Connection closed at byte {}'
- .format(path.stat().st_size))
+ pywikibot.info(
+ f'Connection closed at byte {path.stat().st_size}')
# raised from response.raise_for_status()
except requests.HTTPError as e:
# exit criteria if size is not available
@@ -230,9 +230,8 @@
if self.filename_prefix:
filename = self.filename_prefix + filename
if not self.keep_filename:
- pywikibot.info(
- '\nThe filename on the target wiki will default to: {}\n'
- .format(filename))
+ pywikibot.info(f'\nThe filename on the target wiki will default '
+ f'to: {filename}\n')
assert not self.opt.always
newfn = pywikibot.input(
'Enter a better name, or press enter to accept:')
@@ -412,9 +411,8 @@
comment=self.summary)
except APIError as error:
if error.code == 'uploaddisabled':
- pywikibot.error(
- 'Upload error: Local file uploads are disabled on {}.'
- .format(site))
+ pywikibot.error(f'Upload error: Local file uploads are '
+ f'disabled on {site}.')
elif error.code == 'copyuploadbaddomain' and not download \
and '://' in file_url:
pywikibot.error(error)
@@ -464,8 +462,7 @@
self.upload_file(file_url)
self.counter['read'] += 1
except QuitKeyboardInterrupt:
- pywikibot.info('\nUser quit {} bot run...'
- .format(self.__class__.__name__))
+ pywikibot.info(f'\nUser quit {self.__class__.__name__} bot run...')
except KeyboardInterrupt:
if config.verbose_output:
raise
diff --git a/pywikibot/textlib.py b/pywikibot/textlib.py
index 9078b3c..a1fee36 100644
--- a/pywikibot/textlib.py
+++ b/pywikibot/textlib.py
@@ -173,9 +173,7 @@
"""
first = string[0]
if first.isalpha() and case == 'first-letter':
- pattern = '[{}{}]{}'.format(first.upper(),
- first.lower(),
- re.escape(string[1:]))
+ pattern = f'[{first.upper()}{first.lower()}]{re.escape(string[1:])}'
else:
pattern = re.escape(string)
return pattern
@@ -889,8 +887,8 @@
if must_piped:
new_text = f'[[{new_title}|{new_label}]]'
else:
- new_text = '[[{}]]{}'.format(new_label[:len(new_title)],
- new_label[len(new_title):])
+ new_text = (f'[[{new_label[:len(new_title)]}]]'
+ f'{new_label[len(new_title):]}')
text = text[:start] + new_text + text[end:]
# Make sure that next time around we will not find this same hit.
@@ -1471,13 +1469,12 @@
title, sortKey = rest, None
try:
cat = pywikibot.Category(site,
- '{}:{}'.format(match['namespace'], title),
+ f"{match['namespace']}:{title}",
sort_key=sortKey)
except InvalidTitleError:
# Category title extracted contains invalid characters
# Likely due to on-the-fly category name creation, see T154309
- pywikibot.warning('Invalid category title extracted: {}'
- .format(title))
+ pywikibot.warning(f'Invalid category title extracted: {title}')
else:
result.append(cat)
diff --git a/pywikibot/time.py b/pywikibot/time.py
index da10ecb..8b2a494 100644
--- a/pywikibot/time.py
+++ b/pywikibot/time.py
@@ -445,10 +445,8 @@
key, duration = string[-1], string[:-1]
if key not in MW_KEYS:
- raise ValueError('Time period qualifier is unrecognized: {}'
- .format(string))
+ raise ValueError(f'Time period qualifier is unrecognized: {string}')
if not duration.isdigit():
- raise ValueError("Time period's duration should be numeric: {}"
- .format(string))
+ raise ValueError(f"Time period's duration should be numeric: {string}")
return key, int(duration)
diff --git a/pywikibot/tools/__init__.py b/pywikibot/tools/__init__.py
index 1c0cac5..a2a7802 100644
--- a/pywikibot/tools/__init__.py
+++ b/pywikibot/tools/__init__.py
@@ -646,8 +646,8 @@
stderr=subprocess.PIPE,
bufsize=65535)
except OSError:
- raise ValueError('7za is not installed or cannot uncompress "{}"'
- .format(filename))
+ raise ValueError(
+ f'7za is not installed or cannot uncompress "{filename}"')
stderr = process.stderr.read()
process.stderr.close()
diff --git a/pywikibot/tools/_deprecate.py b/pywikibot/tools/_deprecate.py
index ca6f1eb..cd4b4d9 100644
--- a/pywikibot/tools/_deprecate.py
+++ b/pywikibot/tools/_deprecate.py
@@ -62,8 +62,7 @@
frame = sys._getframe(stacklevel + 1)
class_name = frame.f_code.co_name
if class_name and class_name != '<module>':
- obj.__full_name__ = '{}.{}.{}'.format(obj.__module__,
- class_name, obj.__name__)
+ obj.__full_name__ = f'{obj.__module__}.{class_name}.{obj.__name__}'
else:
obj.__full_name__ = f'{obj.__module__}.{obj.__name__}'
@@ -462,8 +461,7 @@
depth = get_wrapper_depth(wrapper) + 1
args, varargs, kwargs, *_ = getfullargspec(wrapper.__wrapped__)
if varargs is not None and kwargs is not None:
- raise ValueError('{} may not have * or ** args.'
- .format(name))
+ raise ValueError(f'{name} may not have * or ** args.')
deprecated = set(__kw) & set(arg_names)
if len(__args) > len(args):
deprecated.update(arg_names[:len(__args) - len(args)])
@@ -604,13 +602,12 @@
otherwise it provides a DeprecationWarning
"""
if '.' in name:
- raise ValueError('Deprecated name "{}" may not contain '
- '".".'.format(name))
+ raise ValueError(f'Deprecated name "{name}" may not contain ".".')
if name in self._deprecated:
raise ValueError(f'Name "{name}" is already deprecated.')
if replacement is not None and hasattr(self._module, name):
- raise ValueError('Module has already an attribute named '
- '"{}".'.format(name))
+ raise ValueError(
+ f'Module has already an attribute named "{name}".')
if replacement_name is None:
if hasattr(replacement, '__name__'):
diff --git a/pywikibot/tools/chars.py b/pywikibot/tools/chars.py
index c086f4d..c64c84d 100644
--- a/pywikibot/tools/chars.py
+++ b/pywikibot/tools/chars.py
@@ -18,7 +18,7 @@
# At the moment we've only added the characters from the Cf category
_invisible_chars = _category_cf
-INVISIBLE_REGEX = re.compile('[{}]'.format(''.join(_invisible_chars)))
+INVISIBLE_REGEX = re.compile(f"[{''.join(_invisible_chars)}]")
def contains_invisible(text):
diff --git a/pywikibot/tools/djvu.py b/pywikibot/tools/djvu.py
index 2c885c6..68d87e9 100644
--- a/pywikibot/tools/djvu.py
+++ b/pywikibot/tools/djvu.py
@@ -1,6 +1,6 @@
"""Wrapper around djvulibre to access djvu files properties and content."""
#
-# (C) Pywikibot team, 2015-2022
+# (C) Pywikibot team, 2015-2023
#
# Distributed under the terms of the MIT license.
#
@@ -75,9 +75,7 @@
def __repr__(self) -> str:
"""Return a more complete string representation."""
- return "{}.{}('{}')".format(self.__module__,
- self.__class__.__name__,
- self._filename)
+ return f"{self.__module__}.{type(self).__name__}('{self._filename}')"
def __str__(self) -> str:
"""Return a string representation."""
@@ -223,8 +221,7 @@
:param force: if True, refresh the cached data
"""
if not self.has_text(force=force):
- raise ValueError('Djvu file {} has no text layer.'
- .format(self.file))
+ raise ValueError(f'Djvu file {self.file} has no text layer.')
res, stdoutdata = _call_cmd(['djvutxt', f'--page={n}',
self.file])
if not res:
diff --git a/pywikibot/tools/threading.py b/pywikibot/tools/threading.py
index b076a5f..37635a8 100644
--- a/pywikibot/tools/threading.py
+++ b/pywikibot/tools/threading.py
@@ -198,8 +198,7 @@
super().__init__(*args)
for item in self:
if not isinstance(item, threading.Thread):
- raise TypeError("Cannot add '{}' to ThreadList"
- .format(type(item)))
+ raise TypeError(f"Cannot add '{type(item)}' to ThreadList")
def active_count(self):
"""Return the number of alive threads and delete all non-alive ones."""
@@ -214,13 +213,11 @@
def append(self, thd):
"""Add a thread to the pool and start it."""
if not isinstance(thd, threading.Thread):
- raise TypeError("Cannot append '{}' to ThreadList"
- .format(type(thd)))
+ raise TypeError(f"Cannot append '{type(thd)}' to ThreadList")
while self.active_count() >= self.limit:
time.sleep(self.wait_time)
super().append(thd)
thd.start()
- pywikibot.logging.debug("thread {} ('{}') started"
- .format(len(self), type(thd)))
+ pywikibot.logging.debug(f"thread {len(self)} ('{type(thd)}') started")
diff --git a/pywikibot/userinterfaces/terminal_interface_base.py b/pywikibot/userinterfaces/terminal_interface_base.py
index 0f6ecfa..9ba7545 100644
--- a/pywikibot/userinterfaces/terminal_interface_base.py
+++ b/pywikibot/userinterfaces/terminal_interface_base.py
@@ -515,8 +515,7 @@
# lock stream output
with self.lock:
if not force:
- line_template = '{{0: >{}}}: {{1}}\n'.format(
- len(str(len(answers))))
+ line_template = f'{{0: >{len(str(len(answers)))}}}: {{1}}\n'
for i, entry in enumerate(answers, start=1):
self.stream_output(line_template.format(i, entry))
@@ -536,8 +535,7 @@
if force:
raise ValueError(
- 'Invalid value "{}" for default during force.'
- .format(default))
+ f'Invalid value "{default}" for default during force.')
self.stream_output('Error: Invalid response\n')
diff --git a/pywikibot/version.py b/pywikibot/version.py
index 7dd4633..5a05047 100644
--- a/pywikibot/version.py
+++ b/pywikibot/version.py
@@ -107,8 +107,7 @@
# Git and SVN can silently fail, as it may be a nightly.
if exceptions:
- pywikibot.debug('version algorithm exceptions:\n{!r}'
- .format(exceptions))
+ pywikibot.debug(f'version algorithm exceptions:\n{exceptions!r}')
if isinstance(date, str):
datestring = date
@@ -252,7 +251,7 @@
e = tag.find('\n', s)
tag = tag[(s + 6):e]
t = tag.strip().split('/')
- tag = '[{}] {}'.format(t[0][:-1], '-'.join(t[3:]))
+ tag = f"[{t[0][:-1]}] {'-'.join(t[3:])}"
dp = subprocess.Popen([cmd, '--no-pager',
'log', '-1',
'--pretty=format:"%ad|%an|%h|%H|%d"',
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/934674
To unsubscribe, or for help writing mail filters, visit https://gerrit.wikimedia.org/r/settings
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I55d8a55ef7d526ac9f32b40ce131073c08697cdc
Gerrit-Change-Number: 934674
Gerrit-PatchSet: 3
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: JJMC89 <JJMC89.Wikimedia(a)gmail.com>
Gerrit-Reviewer: jenkins-bot
Gerrit-MessageType: merged