XZise has uploaded a new change for review.
https://gerrit.wikimedia.org/r/233102
Change subject: [FEAT] upload: Support ignore warnings callback
......................................................................
[FEAT] upload: Support ignore warnings callback
This supports a callback method which is executed whenever an upload caused a
warning.
Change-Id: I391bb2b7fd4a0f318c5b4537d4b615569413f447
---
M pywikibot/site.py
M scripts/upload.py
2 files changed, 135 insertions(+), 44 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/pywikibot/core
refs/changes/02/233102/1
diff --git a/pywikibot/site.py b/pywikibot/site.py
index c09f399..76ad4b2 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -5196,7 +5196,10 @@
filepage.text will be used, or comment.
@param watch: If true, add filepage to the bot user's watchlist
@param ignore_warnings: if true, ignore API warnings and force
- upload (for example, to overwrite an existing file); default False
+ upload for example, to overwrite an existing file. It is by
default
+ False but can also be a callable getting a list of UploadWarning
+ instances which must either return True or False.
+ @type ignore_warnings: bool or callable
@param chunk_size: The chunk size in bytesfor chunked uploading (see
U{https://www.mediawiki.org/wiki/API:Upload#Chunked_uploading}). It
will only upload in chunks, if the version number is 1.20 or higher
@@ -5209,7 +5212,17 @@
continue a previously canceled chunked upload. If False it treats
that as a finished upload. By default starts at 0.
@type _offset: int or bool
+ @return: If C{ignore_warnings} is a bool it always returns None and
does
+ print a message that the upload was successful. If it's a callable
+ it returns True if the upload was successful and False otherwise.
+ @rtype: bool or None
"""
+ def warnings(response):
+ return [api.UploadWarning(
+ warning, upload_warnings[warning] % {'msg': data},
+ _file_key, response.get('offset', 0))
+ for warning, data in response['warnings'].items()]
+
upload_warnings = {
# map API warning codes to user error messages
# %(msg)s will be replaced by message string from API responsse
@@ -5289,7 +5302,8 @@
'filesize': filesize,
'offset': offset,
'filename': file_page_title,
- 'ignorewarnings': ignore_warnings})
+ 'ignorewarnings': not
callable(ignore_warnings) and
+ ignore_warnings})
req.mime_params['chunk'] = (chunk,
("application",
"octet-stream"),
{'filename':
mime_filename})
@@ -5303,11 +5317,20 @@
if error.code == u'uploaddisabled':
self._uploaddisabled = True
raise error
- if 'warnings' in data and not ignore_warnings:
- result = data
- if 'offset' not in result:
- result['offset'] = 0
- break
+ if 'warnings' in data:
+ if callable(ignore_warnings):
+ if ignore_warnings(warnings(data)):
+ # Future warnings of this run can be
ignored
+ ignore_warnings = True
+ offset = result.get('offset', 0)
+ continue
+ else:
+ return False
+ elif ignore_warnings:
+ result = data
+ if 'offset' not in result:
+ result['offset'] = 0
+ break
_file_key = data['filekey']
throttle = False
if 'offset' in data:
@@ -5345,7 +5368,8 @@
url=source_url, comment=comment, text=text, token=token)
if not result:
final_request['watch'] = watch
- final_request['ignorewarnings'] = ignore_warnings
+ final_request['ignorewarnings'] = (not callable(ignore_warnings)
and
+ ignore_warnings)
try:
result = final_request.submit()
self._uploaddisabled = False
@@ -5357,33 +5381,43 @@
result = result["upload"]
pywikibot.debug(result, _logger)
- if "warnings" in result and not ignore_warnings:
- # TODO: Handle multiple warnings at the same time
- warning = list(result["warnings"].keys())[0]
- message = result["warnings"][warning]
- if 'filekey' in result:
- _file_key = result['filekey']
- elif 'sessionkey' in result:
- # TODO: Probably needs to be reflected in the API call above
- _file_key = result['sessionkey']
- pywikibot.warning('Using sessionkey instead of filekey.')
- else:
- _file_key = None
- pywikibot.warning('No filekey defined.')
- raise pywikibot.UploadWarning(warning, upload_warnings[warning]
- % {'msg': message},
- file_key=_file_key,
- offset=result['offset']
- if 'offset' in result else
False)
- elif "result" not in result:
+ if "warnings" in result:
+ if callable(ignore_warnings):
+ if ignore_warnings(warnings(result)):
+ return self.upload(
+ filepage=filepage, source_filename=source_filename,
source_url=source_url,
+ comment=comment, text=text, watch=watch,
ignore_warnings=True,
+ chunk_size=chunk_size, _file_key=_file_key,
_offset=result.get('offset', False))
+ else:
+ return False
+ elif not ignore_warnings:
+ # TODO: Handle multiple warnings at the same time
+ warning = list(result["warnings"].keys())[0]
+ message = result["warnings"][warning]
+ if 'filekey' in result:
+ _file_key = result['filekey']
+ elif 'sessionkey' in result:
+ # TODO: Probably needs to be reflected in the API call
above
+ _file_key = result['sessionkey']
+ pywikibot.warning('Using sessionkey instead of filekey.')
+ else:
+ _file_key = None
+ pywikibot.warning('No filekey defined.')
+ raise pywikibot.UploadWarning(warning, upload_warnings[warning]
+ % {'msg': message},
+ file_key=_file_key,
+ offset=result['offset']
+ if 'offset' in result
else False)
+ if "result" not in result:
pywikibot.output(u"Upload: unrecognized response: %s" % result)
if result["result"] == "Success":
- pywikibot.output(u"Upload successful.")
+ if not callable(ignore_warnings):
+ pywikibot.output(u"Upload successful.")
# If we receive a nochange, that would mean we're in simulation
# mode, don't attempt to access imageinfo
if "nochange" not in result:
filepage._load_file_revisions([result["imageinfo"]])
- return
+ return result['result'] == 'Success' if callable(ignore_warnings) else
None
@deprecated_args(number='total',
repeat=None,
diff --git a/scripts/upload.py b/scripts/upload.py
index abf0ff7..c1607bb 100755
--- a/scripts/upload.py
+++ b/scripts/upload.py
@@ -23,6 +23,13 @@
'Mi': Mebibytes (1024x1024 B)
The suffixes are case insensitive.
+It is possible to combine -abortonwarn and -ignorewarn so that if the specific
+warning is given it won't apply the general one but more specific one. So if it
+should ignore specific warnings and abort on the rest it's possible by defining
+no warning for -abortonwarn and the specific warnings for -ignorewarn. The
order
+does not matter. If both are unspecific or a warning is specified by both,
it'll
+prefer aborting.
+
If any other arguments are given, the first is either URL, filename or
directory
to upload, and the rest is a proposed description to go with the upload. If
none
of these are given, the user is asked for the directory, file or URL to upload.
@@ -197,6 +204,44 @@
t.close()
return tempname
+ def _handle_warning(self, warning):
+ """
+ Return whether the warning cause an abort or be ignored.
+
+ @param warning: The warning name
+ @type warning: str
+ @return: False if this warning should cause an abort, True if it should
+ be ignored or None if this warning has no default handler.
+ @rtype: bool or None
+ """
+ if self.aborts is not True:
+ if warning in self.aborts:
+ return False
+ if self.ignoreWarning is True or warning in self.ignoreWarning:
+ return True
+ return None if self.aborts is not True else False
+
+ def _handle_warnings(self, warnings):
+ messages = '\n'.join('{0}: {1}'.format(warning.code, warning.info)
+ for warning in sorted(warnings))
+ if len(warnings) > 1:
+ messages = '\n' + messages
+ pywikibot.output('We got the following warning(s): ' + messages)
+ answer = True
+ for warning in warnings:
+ this_answer = self._handle_warning(warning)
+ if this_answer is False:
+ answer = False
+ break
+ elif this_answer is None:
+ answer = None
+ if answer is None:
+ answer = pywikibot.input_yn(u"Do you want to ignore?",
+ default=False, automatic_quit=False)
+ if not answer:
+ pywikibot.output(u"Upload aborted.")
+ return answer
+
def process_filename(self, file_url=None):
"""Return base filename portion of file_url."""
if not file_url:
@@ -351,32 +396,42 @@
pywikibot.output(u'Uploading file to %s via API...' % site)
+ success = False
try:
- apiIgnoreWarnings = False
if self.ignoreWarning is True:
apiIgnoreWarnings = True
+ else:
+ apiIgnoreWarnings = self._handle_warnings
if self.uploadByUrl:
- site.upload(imagepage, source_url=file_url,
- ignore_warnings=apiIgnoreWarnings,
- _file_key=_file_key, _offset=_offset)
+ success = site.upload(imagepage, source_url=file_url,
+ ignore_warnings=apiIgnoreWarnings,
+ _file_key=_file_key, _offset=_offset)
else:
if "://" in file_url:
temp = self.read_file_content(file_url)
else:
temp = file_url
- site.upload(imagepage, source_filename=temp,
- ignore_warnings=apiIgnoreWarnings,
- chunk_size=self.chunk_size,
- _file_key=_file_key, _offset=_offset)
+ success = site.upload(imagepage, source_filename=temp,
+ ignore_warnings=apiIgnoreWarnings,
+ chunk_size=self.chunk_size,
+ _file_key=_file_key, _offset=_offset)
except pywikibot.data.api.UploadWarning as warn:
+ messages = '\n'.join('{0}: {1}'.format(code, msg)
+ for code, msg in
sorted(warn.messages.items()))
+ if len(warn.messages) > 1:
+ messages = '\n' + messages
pywikibot.output(
- u'We got a warning message: {0} - {1}'.format(warn.code,
warn.message))
- if self.abort_on_warn(warn.code):
- answer = False
- elif self.ignore_on_warn(warn.code):
- answer = True
- else:
+ 'We got the following warning(s): ' + messages)
+ answer = True
+ for code in warn.messages:
+ this_answer = self._handle_warning(code)
+ if this_answer is False:
+ answer = False
+ break
+ elif this_answer is None:
+ answer = None
+ if answer is None:
answer = pywikibot.input_yn(u"Do you want to ignore?",
default=False,
automatic_quit=False)
if answer:
@@ -395,10 +450,12 @@
except Exception:
pywikibot.error("Upload error: ", exc_info=True)
- else:
+ if success:
# No warning, upload complete.
pywikibot.output(u"Upload of %s successful." % filename)
return filename # data['filename']
+ else:
+ return None
def run(self):
"""Run bot."""
--
To view, visit https://gerrit.wikimedia.org/r/233102
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I391bb2b7fd4a0f318c5b4537d4b615569413f447
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: XZise <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits