jenkins-bot has submitted this change and it was merged.
Change subject: [IMPR] Provide recentchanges tag filter
......................................................................
[IMPR] Provide recentchanges tag filter
- Add tag filter to site.recentchanges() method
- Add 'tags' to rcprops
- Add tag filter to pagegenerators.RecentChangesPageGenerator
- Enable tag filtering with pagegenerators -recentchanges option
- Add tests for site and pagegenerators methods
Bug: T147416
Change-Id: Ia636aef46dd36b937a78cb71c9b98819753be2ff
---
M pywikibot/pagegenerators.py
M pywikibot/site.py
M tests/pagegenerators_tests.py
M tests/site_tests.py
4 files changed, 38 insertions(+), 8 deletions(-)
Approvals:
Magul: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/pagegenerators.py b/pywikibot/pagegenerators.py
index 605ebd8..0a4ba85 100644
--- a/pywikibot/pagegenerators.py
+++ b/pywikibot/pagegenerators.py
@@ -184,12 +184,17 @@
given as -recentchanges:x, will work on the x most recently
changed pages. If given as -recentchanges:offset,duration it
will work on pages changed from 'offset' minutes with
- 'duration' minutes of timespan.
+ 'duration' minutes of timespan. rctags are supported too.
+ The rctag must be the very first parameter part.
Examples:
-recentchanges:20 gives the 20 most recently changed pages
-recentchanges:120,70 will give pages with 120 offset
minutes and 70 minutes of timespan
+ -recentchanges:visualeditor,10 gives the 10 most recently
+ changed pages marked with 'visualeditor'
+ -recentchanges:"mobile edit,60,35" will retrieve pages marked
+ with 'mobile edit' for the given offset and timespan
-unconnectedpages Work on the most recent unconnected pages to the Wikibase
repository. Given as -unconnectedpages:x, will work on the
@@ -690,8 +695,11 @@
elif arg == '-recentchanges':
rcstart = None
rcend = None
+ rctag = None
total = None
params = value.split(',') if value else []
+ if params and not params[0].isdigit():
+ rctag = params.pop(0)
if len(params) == 2:
offset = float(params[0])
duration = float(params[1])
@@ -700,7 +708,7 @@
elif len(params) > 2:
raise ValueError('More than two parameters passed.')
else:
- total = int(value) if value else 60
+ total = int(params[0]) if params else 60
if len(params) == 2:
ts_time = self.site.server_time()
rcstart = ts_time + timedelta(minutes=-(offset + duration))
@@ -711,6 +719,7 @@
end=rcend,
site=self.site,
reverse=True,
+ tag=rctag,
_filter_unique=self._filter_unique)
elif arg == '-liverecentchanges':
@@ -1089,7 +1098,7 @@
showRedirects=None, showPatrolled=None,
topOnly=False, total=None,
user=None, excludeuser=None, site=None,
- _filter_unique=None):
+ tag=None, _filter_unique=None):
"""
Generate pages that are in the recent changes list, including duplicates.
@@ -1129,7 +1138,8 @@
@type excludeuser: basestring|list
@param site: Site for generator results.
@type site: L{pywikibot.site.BaseSite}
-
+ @param tag: a recent changes tag
+ @type tag: str
"""
if site is None:
site = pywikibot.Site()
@@ -1141,7 +1151,7 @@
showRedirects=showRedirects,
showPatrolled=showPatrolled,
topOnly=topOnly, total=total,
- user=user, excludeuser=excludeuser)
+ user=user, excludeuser=excludeuser, tag=tag)
gen.request['rcprop'] = 'title'
gen = (pywikibot.Page(site, x['title'])
diff --git a/pywikibot/site.py b/pywikibot/site.py
index f4267ca..f2e022e 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -4463,7 +4463,7 @@
namespaces=None, pagelist=None, changetype=None,
showMinor=None, showBot=None, showAnon=None,
showRedirects=None, showPatrolled=None, topOnly=False,
- total=None, user=None, excludeuser=None):
+ total=None, user=None, excludeuser=None, tag=None):
"""Iterate recent changes.
@param start: Timestamp to start listing from
@@ -4504,6 +4504,8 @@
@type user: basestring|list
@param excludeuser: if not None, exclude edits by this user or users
@type excludeuser: basestring|list
+ @param tag: a recent changes tag
+ @type tag: str
@raises KeyError: a namespace identifier was not resolved
@raises TypeError: a namespace identifier has an inappropriate
type such as NoneType or bool
@@ -4513,7 +4515,7 @@
rcgen = self._generator(api.ListGenerator, type_arg="recentchanges",
rcprop="user|comment|timestamp|title|ids"
- "|sizes|redirect|loginfo|flags",
+ '|sizes|redirect|loginfo|flags|tags',
namespaces=namespaces,
total=total, rctoponly=topOnly)
if start is not None:
@@ -4548,7 +4550,7 @@
if excludeuser:
rcgen.request['rcexcludeuser'] = excludeuser
-
+ rcgen.request['rctag'] = tag
return rcgen
@deprecated_args(number='total', step=None, key='searchstring',
diff --git a/tests/pagegenerators_tests.py b/tests/pagegenerators_tests.py
index 4d93a4d..38cd41f 100755
--- a/tests/pagegenerators_tests.py
+++ b/tests/pagegenerators_tests.py
@@ -865,6 +865,14 @@
self.assertIsNotNone(gen)
self.assertPagesInNamespacesAll(gen, set([0, 1, 2]), skip=True)
+ def test_recentchanges_rctag(self):
+ """Test recentchanges generator with recent changes tag."""
+ gf = pagegenerators.GeneratorFactory(site=self.site)
+ gf.handleArg('-recentchanges:visualeditor')
+ gen = gf.getCombinedGenerator()
+ self.assertIsNotNone(gen)
+ self.assertPagesInNamespacesAll(gen, set([0, 1, 2]), skip=True)
+
def test_recentchanges_ns_default(self):
"""Test recentchanges generator."""
gf = pagegenerators.GeneratorFactory(site=self.site)
diff --git a/tests/site_tests.py b/tests/site_tests.py
index 6134f26..189d747 100644
--- a/tests/site_tests.py
+++ b/tests/site_tests.py
@@ -1314,6 +1314,16 @@
self.assertIsInstance(change, dict)
self.assertNotIn("redirect", change)
+ def test_tag_filter(self):
+ """Test the site.recentchanges() with tag filter."""
+ mysite = self.site
+ for tag in ('visualeditor', 'mobile edit'):
+ for change in mysite.recentchanges(tag=tag, total=5):
+ self.assertIsInstance(change, dict)
+ self.assertIn('tags', change)
+ self.assertIsInstance(change['tags'], list)
+ self.assertIn(tag, change['tags'])
+
class TestUserRecentChanges(DefaultSiteTestCase):
--
To view, visit https://gerrit.wikimedia.org/r/316064
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ia636aef46dd36b937a78cb71c9b98819753be2ff
Gerrit-PatchSet: 4
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <Ladsgroup(a)gmail.com>
Gerrit-Reviewer: Magul <tomasz.magulski(a)gmail.com>
Gerrit-Reviewer: Mpaa <mpaa.wiki(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: [bugfix] Show deprecated options warning
......................................................................
[bugfix] Show deprecated options warning
- issue_deprecation_warning doesn't show the deprecated warning by default
when DeprecationWarning class is used. We have to use
ArgumentDeprecationWarning class instead.
- import issue_deprecation_warning to reuse it.
- When an option is deprecated or renamed the new one should be shown but
deprecated or renamed options should be omitted in the help doc. We have
issue_deprecation_warning to show the warning if necessary.
Change-Id: I68fcb0d671d1a6ae2f5969b38aeaec3c91fdc605
---
M scripts/checkimages.py
1 file changed, 7 insertions(+), 9 deletions(-)
Approvals:
Magul: Looks good to me, approved
jenkins-bot: Verified
diff --git a/scripts/checkimages.py b/scripts/checkimages.py
index 8fc472b..35a0a02 100755
--- a/scripts/checkimages.py
+++ b/scripts/checkimages.py
@@ -25,9 +25,6 @@
-duplicatesreport Report the duplicates in a log *AND* put the template in
the images.
--duplicatereport The -duplicatereport option is deprecated. Use
- -duplicatesreport instead.
-
-sendemail Send an email after tagging.
-break To break the bot after the first check (default: recursive)
@@ -102,9 +99,9 @@
from pywikibot import i18n
from pywikibot import pagegenerators as pg
-from pywikibot.exceptions import NotEmailableError
+from pywikibot.exceptions import ArgumentDeprecationWarning, NotEmailableError
from pywikibot.family import Family
-from pywikibot.tools import deprecated, StringTypes
+from pywikibot.tools import deprecated, issue_deprecation_warning, StringTypes
###############################################################################
# <--------------------------- Change only below! --------------------------->#
@@ -1614,7 +1611,8 @@
if arg.startswith('-sleep'):
length = len('-sleep')
else:
- pywikibot.tools.issue_deprecation_warning('-time', '-sleep', 2)
+ issue_deprecation_warning('-time', '-sleep', 2,
+ ArgumentDeprecationWarning)
length = len('-time')
if len(arg) == length:
time_sleep = int(pywikibot.input(
@@ -1629,9 +1627,9 @@
commonsActive = True
elif arg == '-duplicatesreport' or arg == '-duplicatereport':
if arg == '-duplicatereport':
- pywikibot.tools.issue_deprecation_warning('-duplicatereport',
- '-duplicatesreport',
- 2)
+ issue_deprecation_warning('-duplicatereport',
+ '-duplicatesreport',
+ 2, ArgumentDeprecationWarning)
duplicatesReport = True
elif arg.startswith('-duplicates'):
duplicatesActive = True
--
To view, visit https://gerrit.wikimedia.org/r/323691
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I68fcb0d671d1a6ae2f5969b38aeaec3c91fdc605
Gerrit-PatchSet: 3
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Huji <huji.huji(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Magul <tomasz.magulski(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: Fixing two typos in docstring
......................................................................
Fixing two typos in docstring
Follow-up to I2e7113876bc3a150c01701614d13931e1d4819b0
Change-Id: I6d7206b6188df412c4215adf0de9068a065ff946
---
M pywikibot/page.py
M pywikibot/site.py
2 files changed, 4 insertions(+), 4 deletions(-)
Approvals:
Xqt: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/page.py b/pywikibot/page.py
index 0f6d838..2d5fea5 100644
--- a/pywikibot/page.py
+++ b/pywikibot/page.py
@@ -2486,9 +2486,9 @@
a boolean or an iterable. The callable gets a list of UploadWarning
instances and the iterable should contain the warning codes for
which an equivalent callable would return True if all UploadWarning
- codes are in thet list. If the result is False it'll not continuing
+ codes are in thet list. If the result is False it'll not continue
uploading the file and otherwise disable any warning and
- reattempting to upload the file. NOTE: If report_success is True or
+ reattempt to upload the file. NOTE: If report_success is True or
None it'll raise an UploadWarning exception if the static boolean is
False.
@type ignore_warnings: bool or callable or iterable of str
diff --git a/pywikibot/site.py b/pywikibot/site.py
index cd6b1d4..ddfa8e3 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -5872,9 +5872,9 @@
a boolean or an iterable. The callable gets a list of UploadWarning
instances and the iterable should contain the warning codes for
which an equivalent callable would return True if all UploadWarning
- codes are in thet list. If the result is False it'll not continuing
+ codes are in thet list. If the result is False it'll not continue
uploading the file and otherwise disable any warning and
- reattempting to upload the file. NOTE: If report_success is True or
+ reattempt to upload the file. NOTE: If report_success is True or
None it'll raise an UploadWarning exception if the static boolean is
False.
@type ignore_warnings: bool or callable or iterable of str
--
To view, visit https://gerrit.wikimedia.org/r/323857
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I6d7206b6188df412c4215adf0de9068a065ff946
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Lokal Profil <lokal.profil(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: [IMPR] Separate scripts and library part
......................................................................
[IMPR] Separate scripts and library part
- pywikibot framework is designed to separate scripts from library parts
Move UploadRobot to pywikibot.specialbots. Other bots may follow.
- By importing UploadRobot in upload.py other scripts won't break when they
import upload and use upload.UploadRobot
- Anyway fix import in all known scripts using UploadRobot
Bug: T89499
Change-Id: I3a1ec2089930d1a0a9008008c34bc151b27fe5fe
---
A pywikibot/specialbots.py
M scripts/data_ingestion.py
M scripts/flickrripper.py
M scripts/imagecopy.py
M scripts/imagecopy_self.py
M scripts/imageharvest.py
M scripts/imagetransfer.py
M scripts/panoramiopicker.py
M scripts/upload.py
9 files changed, 501 insertions(+), 484 deletions(-)
Approvals:
Lokal Profil: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/specialbots.py b/pywikibot/specialbots.py
new file mode 100644
index 0000000..c524269
--- /dev/null
+++ b/pywikibot/specialbots.py
@@ -0,0 +1,452 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""Library containing special bots."""
+#
+# (C) Rob W.W. Hooft, Andre Engels 2003-2004
+# (C) Pywikibot team, 2003-2016
+#
+# Distributed under the terms of the MIT license.
+#
+from __future__ import absolute_import, unicode_literals
+
+__version__ = '$Id$'
+#
+
+import os
+import sys
+import tempfile
+import time
+
+import pywikibot
+import pywikibot.data.api
+
+from pywikibot import config
+
+from pywikibot.bot import BaseBot
+from pywikibot.tools import (
+ deprecated
+)
+from pywikibot.tools.formatter import color_format
+
+if sys.version_info[0] > 2:
+ from urllib.parse import urlparse
+ from urllib.request import URLopener
+
+ basestring = (str,)
+else:
+ from urllib import URLopener
+ from urlparse import urlparse
+
+
+class UploadRobot(BaseBot):
+
+ """Upload bot."""
+
+ def __init__(self, url, urlEncoding=None, description=u'',
+ useFilename=None, keepFilename=False,
+ verifyDescription=True, ignoreWarning=False,
+ targetSite=None, uploadByUrl=False, aborts=[], chunk_size=0,
+ **kwargs):
+ """
+ Constructor.
+
+ @param url: path to url or local file (deprecated), or list of urls or
+ paths to local files.
+ @type url: string (deprecated) or list
+ @param description: Description of file for its page. If multiple files
+ are uploading the same description is used for every file.
+ @type description: string
+ @param useFilename: Specify title of the file's page. If multiple
+ files are uploading it asks to change the name for second, third,
+ etc. files, otherwise the last file will overwrite the other.
+ @type useFilename: string
+ @param keepFilename: Set to True to keep original names of urls and
+ files, otherwise it will ask to enter a name for each file.
+ @type keepFilename: bool
+ @param verifyDescription: Set to False to not proofread the description.
+ @type verifyDescription: bool
+ @param ignoreWarning: Set this to True to upload even if another file
+ would be overwritten or another mistake would be risked. Set it to
+ an array of warning codes to selectively ignore specific warnings.
+ @type ignoreWarning: bool or list
+ @param targetSite: Set the site to upload to. If target site is not
+ given it's taken from user-config.py.
+ @type targetSite: object
+ @param aborts: List of the warning types to abort upload on. Set to True
+ to abort on any warning.
+ @type aborts: bool or list
+ @param chunk_size: Upload the file in chunks (more overhead, but
+ restartable) specified in bytes. If no value is specified the file
+ will be uploaded as whole.
+ @type chunk_size: integer
+ @param always: Disables any input, requires that either ignoreWarning or
+ aborts are set to True and that the description is also set. It will
+ overwrite verifyDescription to False and keepFilename to True.
+ @type always: bool
+
+ @deprecated: Using upload_image() is deprecated, use upload_file() with
+ file_url param instead
+
+ """
+ super(UploadRobot, self).__init__(**kwargs)
+ always = self.getOption('always')
+ if (always and ignoreWarning is not True and aborts is not True):
+ raise ValueError('When always is set to True, either ignoreWarning '
+ 'or aborts must be set to True.')
+ if always and not description:
+ raise ValueError('When always is set to True the description must '
+ 'be set.')
+ self.url = url
+ if isinstance(self.url, basestring):
+ pywikibot.warning("url as string is deprecated. "
+ "Use an iterable instead.")
+ self.urlEncoding = urlEncoding
+ self.description = description
+ self.useFilename = useFilename
+ self.keepFilename = keepFilename or always
+ self.verifyDescription = verifyDescription and not always
+ self.ignoreWarning = ignoreWarning
+ self.aborts = aborts
+ self.chunk_size = chunk_size
+ if config.upload_to_commons:
+ self.targetSite = targetSite or pywikibot.Site('commons',
+ 'commons')
+ else:
+ self.targetSite = targetSite or pywikibot.Site()
+ self.targetSite.login()
+ self.uploadByUrl = uploadByUrl
+
+ @deprecated()
+ def urlOK(self):
+ """Return True if self.url is a URL or an existing local file."""
+ return "://" in self.url or os.path.exists(self.url)
+
+ def read_file_content(self, file_url=None):
+ """Return name of temp file in which remote file is saved."""
+ if not file_url:
+ file_url = self.url
+ pywikibot.warning("file_url is not given. "
+ "Set to self.url by default.")
+ pywikibot.output(u'Reading file %s' % file_url)
+ resume = False
+ rlen = 0
+ _contents = None
+ dt = 15
+ uo = URLopener()
+ retrieved = False
+
+ while not retrieved:
+ if resume:
+ pywikibot.output(u"Resume download...")
+ uo.addheader('Range', 'bytes=%s-' % rlen)
+
+ infile = uo.open(file_url)
+
+ if 'text/html' in infile.info().getheader('Content-Type'):
+ pywikibot.output(u"Couldn't download the image: "
+ "the requested URL was not found on server.")
+ return
+
+ content_len = infile.info().getheader('Content-Length')
+ accept_ranges = infile.info().getheader('Accept-Ranges') == 'bytes'
+
+ if resume:
+ _contents += infile.read()
+ else:
+ _contents = infile.read()
+
+ infile.close()
+ retrieved = True
+
+ if content_len:
+ rlen = len(_contents)
+ content_len = int(content_len)
+ if rlen < content_len:
+ retrieved = False
+ pywikibot.output(
+ u"Connection closed at byte %s (%s left)"
+ % (rlen, content_len))
+ if accept_ranges and rlen > 0:
+ resume = True
+ pywikibot.output(u"Sleeping for %d seconds..." % dt)
+ time.sleep(dt)
+ if dt <= 60:
+ dt += 15
+ elif dt < 360:
+ dt += 60
+ else:
+ pywikibot.log(
+ u"WARNING: length check of retrieved data not possible.")
+ handle, tempname = tempfile.mkstemp()
+ with os.fdopen(handle, "wb") as t:
+ t.write(_contents)
+ 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 (self.ignoreWarning is not False and
+ 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.code}: {0.info}'.format(warning)
+ for warning in sorted(warnings,
+ key=lambda w: w.code))
+ 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.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)
+ return answer
+
+ def process_filename(self, file_url=None):
+ """Return base filename portion of file_url."""
+ if not file_url:
+ file_url = self.url
+ pywikibot.warning("file_url is not given. "
+ "Set to self.url by default.")
+
+ always = self.getOption('always')
+ # Isolate the pure name
+ filename = file_url
+ # Filename may be either a URL or a local file path
+ if "://" in filename:
+ # extract the path portion of the URL
+ filename = urlparse(filename).path
+ filename = os.path.basename(filename)
+ if self.useFilename:
+ filename = self.useFilename
+ if not self.keepFilename:
+ pywikibot.output(
+ u"The filename on the target wiki will default to: %s"
+ % filename)
+ assert not always
+ newfn = pywikibot.input(
+ u'Enter a better name, or press enter to accept:')
+ if newfn != "":
+ filename = newfn
+ # FIXME: these 2 belong somewhere else, presumably in family
+ # forbidden characters are handled by pywikibot/page.py
+ forbidden = ':*?/\\' # to be extended
+ try:
+ allowed_formats = self.targetSite.siteinfo.get(
+ 'fileextensions', get_default=False)
+ except KeyError:
+ allowed_formats = []
+ else:
+ allowed_formats = [item['ext'] for item in allowed_formats]
+
+ # ask until it's valid
+ first_check = True
+ while True:
+ if not first_check:
+ if always:
+ filename = None
+ else:
+ filename = pywikibot.input('Enter a better name, or press '
+ 'enter to skip the file:')
+ if not filename:
+ return None
+ first_check = False
+ ext = os.path.splitext(filename)[1].lower().strip('.')
+ # are any chars in forbidden also in filename?
+ invalid = set(forbidden) & set(filename)
+ if invalid:
+ c = "".join(invalid)
+ pywikibot.output(
+ 'Invalid character(s): %s. Please try again' % c)
+ continue
+ if allowed_formats and ext not in allowed_formats:
+ if always:
+ pywikibot.output('File format is not one of '
+ '[{0}]'.format(' '.join(allowed_formats)))
+ continue
+ elif not pywikibot.input_yn(
+ u"File format is not one of [%s], but %s. Continue?"
+ % (u' '.join(allowed_formats), ext),
+ default=False, automatic_quit=False):
+ continue
+ potential_file_page = pywikibot.FilePage(self.targetSite, filename)
+ if potential_file_page.exists():
+ overwrite = self._handle_warning('exists')
+ if overwrite is False:
+ pywikibot.output("File exists and you asked to abort. Skipping.")
+ return None
+ if potential_file_page.canBeEdited():
+ if overwrite is None:
+ overwrite = not pywikibot.input_yn(
+ "File with name %s already exists. "
+ "Would you like to change the name? "
+ "(Otherwise file will be overwritten.)"
+ % filename, default=True,
+ automatic_quit=False)
+ if not overwrite:
+ continue
+ else:
+ break
+ else:
+ pywikibot.output(u"File with name %s already exists and "
+ "cannot be overwritten." % filename)
+ continue
+ else:
+ try:
+ if potential_file_page.fileIsShared():
+ pywikibot.output(u"File with name %s already exists in shared "
+ "repository and cannot be overwritten."
+ % filename)
+ continue
+ else:
+ break
+ except pywikibot.NoPage:
+ break
+
+ # A proper description for the submission.
+ # Empty descriptions are not accepted.
+ pywikibot.output(u'The suggested description is:\n%s'
+ % self.description)
+
+ # Description must be set and verified
+ if not self.description:
+ self.verifyDescription = True
+
+ while not self.description or self.verifyDescription:
+ if not self.description:
+ pywikibot.output(color_format(
+ '{lightred}It is not possible to upload a file '
+ 'without a summary/description.{default}'))
+
+ assert not always
+ # if no description, default is 'yes'
+ if pywikibot.input_yn(
+ u'Do you want to change this description?',
+ default=not self.description):
+ from pywikibot import editor as editarticle
+ editor = editarticle.TextEditor()
+ try:
+ newDescription = editor.edit(self.description)
+ except Exception as e:
+ pywikibot.error(e)
+ continue
+ # if user saved / didn't press Cancel
+ if newDescription:
+ self.description = newDescription
+ self.verifyDescription = False
+
+ return filename
+
+ def abort_on_warn(self, warn_code):
+ """Determine if the warning message should cause an abort."""
+ if self.aborts is True:
+ return True
+ else:
+ return warn_code in self.aborts
+
+ def ignore_on_warn(self, warn_code):
+ """Determine if the warning message should be ignored."""
+ if self.ignoreWarning is True:
+ return True
+ else:
+ return warn_code in self.ignoreWarning
+
+ @deprecated('UploadRobot.upload_file()')
+ def upload_image(self, debug=False):
+ """Upload image."""
+ self.upload_file(self.url, debug)
+
+ def upload_file(self, file_url, debug=False, _file_key=None, _offset=0):
+ """Upload the image at file_url to the target wiki.
+
+ Return the filename that was used to upload the image.
+ If the upload fails, ask the user whether to try again or not.
+ If the user chooses not to retry, return null.
+
+ """
+ filename = self.process_filename(file_url)
+ if not filename:
+ return None
+
+ site = self.targetSite
+ imagepage = pywikibot.FilePage(site, filename) # normalizes filename
+ imagepage.text = self.description
+
+ pywikibot.output(u'Uploading file to %s via API...' % site)
+
+ success = False
+ try:
+ if self.ignoreWarning is True:
+ apiIgnoreWarnings = True
+ else:
+ apiIgnoreWarnings = self._handle_warnings
+ if self.uploadByUrl:
+ 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
+ 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.APIError as error:
+ if error.code == u'uploaddisabled':
+ pywikibot.error("Upload error: Local file uploads are disabled on %s."
+ % site)
+ else:
+ pywikibot.error("Upload error: ", exc_info=True)
+ return None
+ except Exception:
+ pywikibot.error("Upload error: ", exc_info=True)
+ return None
+ else:
+ if success:
+ # No warning, upload complete.
+ pywikibot.output(u"Upload of %s successful." % filename)
+ return filename # data['filename']
+ else:
+ pywikibot.output(u"Upload aborted.")
+ return None
+
+ def run(self):
+ """Run bot."""
+ # early check that upload is enabled
+ if self.targetSite.is_uploaddisabled():
+ pywikibot.error(
+ "Upload error: Local file uploads are disabled on %s."
+ % self.targetSite)
+ return
+
+ # early check that user has proper rights to upload
+ if "upload" not in self.targetSite.userinfo["rights"]:
+ pywikibot.error(
+ "User '%s' does not have upload rights on site %s."
+ % (self.targetSite.user(), self.targetSite))
+ return
+ if isinstance(self.url, basestring):
+ return self.upload_file(self.url)
+ for file_url in self.url:
+ self.upload_file(file_url)
diff --git a/scripts/data_ingestion.py b/scripts/data_ingestion.py
index d8b0ca7..e1c9a51 100755
--- a/scripts/data_ingestion.py
+++ b/scripts/data_ingestion.py
@@ -38,9 +38,8 @@
from pywikibot import pagegenerators
from pywikibot.comms.http import fetch
+from pywikibot.specialbots import UploadRobot
from pywikibot.tools import deprecated, deprecated_args
-
-from scripts import upload
if sys.version_info[0] > 2:
from urllib.parse import urlparse
@@ -203,12 +202,12 @@
title = photo.getTitle(self.titlefmt)
description = photo.getDescription(self.pagefmt)
- bot = upload.UploadRobot(url=photo.URL,
- description=description,
- useFilename=title,
- keepFilename=True,
- verifyDescription=False,
- targetSite=self.site)
+ bot = UploadRobot(url=photo.URL,
+ description=description,
+ useFilename=title,
+ keepFilename=True,
+ verifyDescription=False,
+ targetSite=self.site)
bot._contents = photo.downloadPhoto().getvalue()
bot._retrieved = True
bot.run()
diff --git a/scripts/flickrripper.py b/scripts/flickrripper.py
index d86f640..9782f91 100755
--- a/scripts/flickrripper.py
+++ b/scripts/flickrripper.py
@@ -25,7 +25,7 @@
"""
#
# (C) Multichill, 2009
-# (C) Pywikibot team, 2009-2014
+# (C) Pywikibot team, 2009-2016
#
# Distributed under the terms of the MIT license.
#
@@ -59,7 +59,7 @@
from pywikibot import config, textlib
from pywikibot.comms.http import fetch
-from scripts import upload
+from pywikibot.specialbots import UploadRobot
try:
from pywikibot.userinterfaces.gui import Tkdialog
@@ -330,11 +330,11 @@
# Would be nice to check before I upload if the file is already at Commons
# Not that important for this program, but maybe for derived programs
if not skip:
- bot = upload.UploadRobot(photoUrl,
- description=newPhotoDescription,
- useFilename=newFilename,
- keepFilename=True,
- verifyDescription=False)
+ bot = UploadRobot(photoUrl,
+ description=newPhotoDescription,
+ useFilename=newFilename,
+ keepFilename=True,
+ verifyDescription=False)
bot.upload_image(debug=False)
return 1
else:
diff --git a/scripts/imagecopy.py b/scripts/imagecopy.py
index ce82757..fc5b71e 100644
--- a/scripts/imagecopy.py
+++ b/scripts/imagecopy.py
@@ -95,9 +95,10 @@
from pywikibot import pagegenerators, config, i18n
+from pywikibot.specialbots import UploadRobot
from pywikibot.tools import PY2
-from scripts import image, upload
+from scripts import image
if not PY2:
import tkinter as Tkinter
@@ -292,11 +293,10 @@
'added categories -->', '')
CH += u'[[Category:' + self.category + u']]'
- bot = upload.UploadRobot(url=self.imagePage.fileUrl(), description=CH,
- useFilename=self.newname, keepFilename=True,
- verifyDescription=False, ignoreWarning=True,
- targetSite=pywikibot.Site('commons',
- 'commons'))
+ bot = UploadRobot(url=self.imagePage.fileUrl(), description=CH,
+ useFilename=self.newname, keepFilename=True,
+ verifyDescription=False, ignoreWarning=True,
+ targetSite=pywikibot.Site('commons', 'commons'))
bot.run()
# Should check if the image actually was uploaded
diff --git a/scripts/imagecopy_self.py b/scripts/imagecopy_self.py
index 3b4eb1d..e55d945 100644
--- a/scripts/imagecopy_self.py
+++ b/scripts/imagecopy_self.py
@@ -63,9 +63,10 @@
from pywikibot import pagegenerators, i18n
+from pywikibot.specialbots import UploadRobot
from pywikibot.tools import PY2
-from scripts import imagerecat, image, upload
+from scripts import imagerecat, image
if not PY2:
import tkinter as Tkinter
@@ -890,13 +891,12 @@
"""Work on a single image."""
cid = self.buildNewImageDescription(fields)
pywikibot.output(cid)
- bot = upload.UploadRobot(url=fields.get('imagepage').fileUrl(),
- description=cid,
- useFilename=fields.get('filename'),
- keepFilename=True, verifyDescription=False,
- ignoreWarning=True,
- targetSite=pywikibot.Site('commons',
- 'commons'))
+ bot = UploadRobot(url=fields.get('imagepage').fileUrl(),
+ description=cid,
+ useFilename=fields.get('filename'),
+ keepFilename=True, verifyDescription=False,
+ ignoreWarning=True,
+ targetSite=pywikibot.Site('commons', 'commons'))
bot.run()
self.tagNowcommons(fields.get('imagepage'), fields.get('filename'))
diff --git a/scripts/imageharvest.py b/scripts/imageharvest.py
index 9026843..eee58ca 100644
--- a/scripts/imageharvest.py
+++ b/scripts/imageharvest.py
@@ -31,9 +31,8 @@
import pywikibot
+from pywikibot.specialbots import UploadRobot
from pywikibot.tools import PY2
-
-from scripts import upload
if not PY2:
import urllib
@@ -122,7 +121,7 @@
% (mysite.namespace(14), cat))
desc += "\r\n\r\n" + basicdesc + "\r\n\r\n" + \
"\r\n".join(categories)
- uploadBot = upload.UploadRobot(image, description=desc)
+ uploadBot = UploadRobot(image, description=desc)
uploadBot.run()
elif answer == 's':
break
diff --git a/scripts/imagetransfer.py b/scripts/imagetransfer.py
index 7c2a0fe..2eea20a 100755
--- a/scripts/imagetransfer.py
+++ b/scripts/imagetransfer.py
@@ -27,7 +27,7 @@
"""
#
# (C) Andre Engels, 2004
-# (C) Pywikibot team, 2004-2015
+# (C) Pywikibot team, 2004-2016
#
# Distributed under the terms of the MIT license.
#
@@ -41,8 +41,8 @@
import pywikibot
from pywikibot import config, i18n, pagegenerators, textlib
+from pywikibot.specialbots import UploadRobot
-from scripts import upload
nowCommonsTemplate = {
'ar': u'{{الآن كومنز|%s}}',
@@ -168,12 +168,12 @@
description = ''
print("Image description page is redirect.")
else:
- bot = upload.UploadRobot(url=url, description=description,
- targetSite=self.targetSite,
- urlEncoding=sourceSite.encoding(),
- keepFilename=self.keep_name,
- verifyDescription=not self.keep_name,
- ignoreWarning=self.ignore_warning)
+ bot = UploadRobot(url=url, description=description,
+ targetSite=self.targetSite,
+ urlEncoding=sourceSite.encoding(),
+ keepFilename=self.keep_name,
+ verifyDescription=not self.keep_name,
+ ignoreWarning=self.ignore_warning)
# try to upload
targetFilename = bot.run()
if targetFilename and self.targetSite.family.name == 'commons' and \
diff --git a/scripts/panoramiopicker.py b/scripts/panoramiopicker.py
index 6dbc4a5..6108ff3 100644
--- a/scripts/panoramiopicker.py
+++ b/scripts/panoramiopicker.py
@@ -3,7 +3,7 @@
"""Tool to copy a Panoramio set to Commons."""
#
# (C) Multichill, 2010
-# (C) Pywikibot team, 2010-2015
+# (C) Pywikibot team, 2010-2016
#
# Distributed under the terms of the MIT license.
#
@@ -24,9 +24,10 @@
from pywikibot import config
+from pywikibot.specialbots import UploadRobot
from pywikibot.tools import PY2
-from scripts import imagerecat, upload
+from scripts import imagerecat
if not PY2:
from urllib.request import urlopen
@@ -242,11 +243,11 @@
# Not that important for this program, but maybe for derived
# programs
if not skip:
- bot = upload.UploadRobot(photoInfo.get(u'photo_file_url'),
- description=newDescription,
- useFilename=newFilename,
- keepFilename=True,
- verifyDescription=False, site=site)
+ bot = UploadRobot(photoInfo.get(u'photo_file_url'),
+ description=newDescription,
+ useFilename=newFilename,
+ keepFilename=True,
+ verifyDescription=False, site=site)
bot.upload_image(debug=False)
return 1
return 0
diff --git a/scripts/upload.py b/scripts/upload.py
index 3f9935d..46b40e2 100755
--- a/scripts/upload.py
+++ b/scripts/upload.py
@@ -47,7 +47,7 @@
"""
#
# (C) Rob W.W. Hooft, Andre Engels 2003-2004
-# (C) Pywikibot team, 2003-2015
+# (C) Pywikibot team, 2003-2016
#
# Distributed under the terms of the MIT license.
#
@@ -55,447 +55,13 @@
__version__ = '$Id$'
#
-
import math
import os
import re
-import sys
-import tempfile
-import time
import pywikibot
-import pywikibot.data.api
-
-from pywikibot import config
-
-from pywikibot.bot import suggest_help, BaseBot
-from pywikibot.tools import (
- deprecated
-)
-from pywikibot.tools.formatter import color_format
-
-if sys.version_info[0] > 2:
- from urllib.parse import urlparse
- from urllib.request import URLopener
-
- basestring = (str,)
-else:
- from urllib import URLopener
- from urlparse import urlparse
-
-
-class UploadRobot(BaseBot):
-
- """Upload bot."""
-
- def __init__(self, url, urlEncoding=None, description=u'',
- useFilename=None, keepFilename=False,
- verifyDescription=True, ignoreWarning=False,
- targetSite=None, uploadByUrl=False, aborts=[], chunk_size=0,
- **kwargs):
- """
- Constructor.
-
- @param url: path to url or local file (deprecated), or list of urls or
- paths to local files.
- @type url: string (deprecated) or list
- @param description: Description of file for its page. If multiple files
- are uploading the same description is used for every file.
- @type description: string
- @param useFilename: Specify title of the file's page. If multiple
- files are uploading it asks to change the name for second, third,
- etc. files, otherwise the last file will overwrite the other.
- @type useFilename: string
- @param keepFilename: Set to True to keep original names of urls and
- files, otherwise it will ask to enter a name for each file.
- @type keepFilename: bool
- @param verifyDescription: Set to False to not proofread the description.
- @type verifyDescription: bool
- @param ignoreWarning: Set this to True to upload even if another file
- would be overwritten or another mistake would be risked. Set it to
- an array of warning codes to selectively ignore specific warnings.
- @type ignoreWarning: bool or list
- @param targetSite: Set the site to upload to. If target site is not
- given it's taken from user-config.py.
- @type targetSite: object
- @param aborts: List of the warning types to abort upload on. Set to True
- to abort on any warning.
- @type aborts: bool or list
- @param chunk_size: Upload the file in chunks (more overhead, but
- restartable) specified in bytes. If no value is specified the file
- will be uploaded as whole.
- @type chunk_size: integer
- @param always: Disables any input, requires that either ignoreWarning or
- aborts are set to True and that the description is also set. It will
- overwrite verifyDescription to False and keepFilename to True.
- @type always: bool
-
- @deprecated: Using upload_image() is deprecated, use upload_file() with
- file_url param instead
-
- """
- super(UploadRobot, self).__init__(**kwargs)
- always = self.getOption('always')
- if (always and ignoreWarning is not True and aborts is not True):
- raise ValueError('When always is set to True, either ignoreWarning '
- 'or aborts must be set to True.')
- if always and not description:
- raise ValueError('When always is set to True the description must '
- 'be set.')
- self.url = url
- if isinstance(self.url, basestring):
- pywikibot.warning("url as string is deprecated. "
- "Use an iterable instead.")
- self.urlEncoding = urlEncoding
- self.description = description
- self.useFilename = useFilename
- self.keepFilename = keepFilename or always
- self.verifyDescription = verifyDescription and not always
- self.ignoreWarning = ignoreWarning
- self.aborts = aborts
- self.chunk_size = chunk_size
- if config.upload_to_commons:
- self.targetSite = targetSite or pywikibot.Site('commons',
- 'commons')
- else:
- self.targetSite = targetSite or pywikibot.Site()
- self.targetSite.login()
- self.uploadByUrl = uploadByUrl
-
- @deprecated()
- def urlOK(self):
- """Return True if self.url is a URL or an existing local file."""
- return "://" in self.url or os.path.exists(self.url)
-
- def read_file_content(self, file_url=None):
- """Return name of temp file in which remote file is saved."""
- if not file_url:
- file_url = self.url
- pywikibot.warning("file_url is not given. "
- "Set to self.url by default.")
- pywikibot.output(u'Reading file %s' % file_url)
- resume = False
- rlen = 0
- _contents = None
- dt = 15
- uo = URLopener()
- retrieved = False
-
- while not retrieved:
- if resume:
- pywikibot.output(u"Resume download...")
- uo.addheader('Range', 'bytes=%s-' % rlen)
-
- infile = uo.open(file_url)
-
- if 'text/html' in infile.info().getheader('Content-Type'):
- pywikibot.output(u"Couldn't download the image: "
- "the requested URL was not found on server.")
- return
-
- content_len = infile.info().getheader('Content-Length')
- accept_ranges = infile.info().getheader('Accept-Ranges') == 'bytes'
-
- if resume:
- _contents += infile.read()
- else:
- _contents = infile.read()
-
- infile.close()
- retrieved = True
-
- if content_len:
- rlen = len(_contents)
- content_len = int(content_len)
- if rlen < content_len:
- retrieved = False
- pywikibot.output(
- u"Connection closed at byte %s (%s left)"
- % (rlen, content_len))
- if accept_ranges and rlen > 0:
- resume = True
- pywikibot.output(u"Sleeping for %d seconds..." % dt)
- time.sleep(dt)
- if dt <= 60:
- dt += 15
- elif dt < 360:
- dt += 60
- else:
- pywikibot.log(
- u"WARNING: length check of retrieved data not possible.")
- handle, tempname = tempfile.mkstemp()
- with os.fdopen(handle, "wb") as t:
- t.write(_contents)
- 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 (self.ignoreWarning is not False and
- 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.code}: {0.info}'.format(warning)
- for warning in sorted(warnings,
- key=lambda w: w.code))
- 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.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)
- return answer
-
- def process_filename(self, file_url=None):
- """Return base filename portion of file_url."""
- if not file_url:
- file_url = self.url
- pywikibot.warning("file_url is not given. "
- "Set to self.url by default.")
-
- always = self.getOption('always')
- # Isolate the pure name
- filename = file_url
- # Filename may be either a URL or a local file path
- if "://" in filename:
- # extract the path portion of the URL
- filename = urlparse(filename).path
- filename = os.path.basename(filename)
- if self.useFilename:
- filename = self.useFilename
- if not self.keepFilename:
- pywikibot.output(
- u"The filename on the target wiki will default to: %s"
- % filename)
- assert not always
- newfn = pywikibot.input(
- u'Enter a better name, or press enter to accept:')
- if newfn != "":
- filename = newfn
- # FIXME: these 2 belong somewhere else, presumably in family
- # forbidden characters are handled by pywikibot/page.py
- forbidden = ':*?/\\' # to be extended
- try:
- allowed_formats = self.targetSite.siteinfo.get(
- 'fileextensions', get_default=False)
- except KeyError:
- allowed_formats = []
- else:
- allowed_formats = [item['ext'] for item in allowed_formats]
-
- # ask until it's valid
- first_check = True
- while True:
- if not first_check:
- if always:
- filename = None
- else:
- filename = pywikibot.input('Enter a better name, or press '
- 'enter to skip the file:')
- if not filename:
- return None
- first_check = False
- ext = os.path.splitext(filename)[1].lower().strip('.')
- # are any chars in forbidden also in filename?
- invalid = set(forbidden) & set(filename)
- if invalid:
- c = "".join(invalid)
- pywikibot.output(
- 'Invalid character(s): %s. Please try again' % c)
- continue
- if allowed_formats and ext not in allowed_formats:
- if always:
- pywikibot.output('File format is not one of '
- '[{0}]'.format(' '.join(allowed_formats)))
- continue
- elif not pywikibot.input_yn(
- u"File format is not one of [%s], but %s. Continue?"
- % (u' '.join(allowed_formats), ext),
- default=False, automatic_quit=False):
- continue
- potential_file_page = pywikibot.FilePage(self.targetSite, filename)
- if potential_file_page.exists():
- overwrite = self._handle_warning('exists')
- if overwrite is False:
- pywikibot.output("File exists and you asked to abort. Skipping.")
- return None
- if potential_file_page.canBeEdited():
- if overwrite is None:
- overwrite = not pywikibot.input_yn(
- "File with name %s already exists. "
- "Would you like to change the name? "
- "(Otherwise file will be overwritten.)"
- % filename, default=True,
- automatic_quit=False)
- if not overwrite:
- continue
- else:
- break
- else:
- pywikibot.output(u"File with name %s already exists and "
- "cannot be overwritten." % filename)
- continue
- else:
- try:
- if potential_file_page.fileIsShared():
- pywikibot.output(u"File with name %s already exists in shared "
- "repository and cannot be overwritten."
- % filename)
- continue
- else:
- break
- except pywikibot.NoPage:
- break
-
- # A proper description for the submission.
- # Empty descriptions are not accepted.
- pywikibot.output(u'The suggested description is:\n%s'
- % self.description)
-
- # Description must be set and verified
- if not self.description:
- self.verifyDescription = True
-
- while not self.description or self.verifyDescription:
- if not self.description:
- pywikibot.output(color_format(
- '{lightred}It is not possible to upload a file '
- 'without a summary/description.{default}'))
-
- assert not always
- # if no description, default is 'yes'
- if pywikibot.input_yn(
- u'Do you want to change this description?',
- default=not self.description):
- from pywikibot import editor as editarticle
- editor = editarticle.TextEditor()
- try:
- newDescription = editor.edit(self.description)
- except Exception as e:
- pywikibot.error(e)
- continue
- # if user saved / didn't press Cancel
- if newDescription:
- self.description = newDescription
- self.verifyDescription = False
-
- return filename
-
- def abort_on_warn(self, warn_code):
- """Determine if the warning message should cause an abort."""
- if self.aborts is True:
- return True
- else:
- return warn_code in self.aborts
-
- def ignore_on_warn(self, warn_code):
- """Determine if the warning message should be ignored."""
- if self.ignoreWarning is True:
- return True
- else:
- return warn_code in self.ignoreWarning
-
- @deprecated('UploadRobot.upload_file()')
- def upload_image(self, debug=False):
- """Upload image."""
- self.upload_file(self.url, debug)
-
- def upload_file(self, file_url, debug=False, _file_key=None, _offset=0):
- """Upload the image at file_url to the target wiki.
-
- Return the filename that was used to upload the image.
- If the upload fails, ask the user whether to try again or not.
- If the user chooses not to retry, return null.
-
- """
- filename = self.process_filename(file_url)
- if not filename:
- return None
-
- site = self.targetSite
- imagepage = pywikibot.FilePage(site, filename) # normalizes filename
- imagepage.text = self.description
-
- pywikibot.output(u'Uploading file to %s via API...' % site)
-
- success = False
- try:
- if self.ignoreWarning is True:
- apiIgnoreWarnings = True
- else:
- apiIgnoreWarnings = self._handle_warnings
- if self.uploadByUrl:
- 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
- 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.APIError as error:
- if error.code == u'uploaddisabled':
- pywikibot.error("Upload error: Local file uploads are disabled on %s."
- % site)
- else:
- pywikibot.error("Upload error: ", exc_info=True)
- return None
- except Exception:
- pywikibot.error("Upload error: ", exc_info=True)
- return None
- else:
- if success:
- # No warning, upload complete.
- pywikibot.output(u"Upload of %s successful." % filename)
- return filename # data['filename']
- else:
- pywikibot.output(u"Upload aborted.")
- return None
-
- def run(self):
- """Run bot."""
- # early check that upload is enabled
- if self.targetSite.is_uploaddisabled():
- pywikibot.error(
- "Upload error: Local file uploads are disabled on %s."
- % self.targetSite)
- return
-
- # early check that user has proper rights to upload
- if "upload" not in self.targetSite.userinfo["rights"]:
- pywikibot.error(
- "User '%s' does not have upload rights on site %s."
- % (self.targetSite.user(), self.targetSite))
- return
- if isinstance(self.url, basestring):
- return self.upload_file(self.url)
- for file_url in self.url:
- self.upload_file(file_url)
+from pywikibot.bot import suggest_help
+from pywikibot.specialbots import UploadRobot
def main(*args):
--
To view, visit https://gerrit.wikimedia.org/r/283422
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I3a1ec2089930d1a0a9008008c34bc151b27fe5fe
Gerrit-PatchSet: 5
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Lokal Profil <lokal.profil(a)gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: Multichill <maarten(a)mdammers.nl>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: [IMPR] Add upload to FilePage
......................................................................
[IMPR] Add upload to FilePage
Bug: T68561
Change-Id: I2e7113876bc3a150c01701614d13931e1d4819b0
---
M pywikibot/page.py
1 file changed, 61 insertions(+), 0 deletions(-)
Approvals:
Lokal Profil: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/page.py b/pywikibot/page.py
index dc83ae4..6acb996 100644
--- a/pywikibot/page.py
+++ b/pywikibot/page.py
@@ -2409,6 +2409,67 @@
"""
return self.site.imageusage(self, total=total, content=content)
+ def upload(self, source, **kwargs):
+ """
+ Upload this file to the wiki.
+
+ keyword arguments are from site.upload() method.
+
+ @param source: Path or URL to the file to be uploaded.
+ @type source: str
+
+ @keyword comment: Edit summary; if this is not provided, then
+ filepage.text will be used. An empty summary is not permitted.
+ This may also serve as the initial page text (see below).
+ @keyword text: Initial page text; if this is not set, then
+ filepage.text will be used, or comment.
+ @keyword watch: If true, add filepage to the bot user's watchlist
+ @keyword ignore_warnings: It may be a static boolean, a callable returning
+ a boolean or an iterable. The callable gets a list of UploadWarning
+ instances and the iterable should contain the warning codes for
+ which an equivalent callable would return True if all UploadWarning
+ codes are in thet list. If the result is False it'll not continuing
+ uploading the file and otherwise disable any warning and
+ reattempting to upload the file. NOTE: If report_success is True or
+ None it'll raise an UploadWarning exception if the static boolean is
+ False.
+ @type ignore_warnings: bool or callable or iterable of str
+ @keyword 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
+ and the chunk size is positive but lower than the file size.
+ @type chunk_size: int
+ @keyword _file_key: Reuses an already uploaded file using the filekey. If
+ None (default) it will upload the file.
+ @type _file_key: str or None
+ @keyword _offset: When file_key is not None this can be an integer to
+ continue a previously canceled chunked upload. If False it treats
+ that as a finished upload. If True it requests the stash info from
+ the server to determine the offset. By default starts at 0.
+ @type _offset: int or bool
+ @keyword _verify_stash: Requests the SHA1 and file size uploaded and
+ compares it to the local file. Also verifies that _offset is
+ matching the file size if the _offset is an int. If _offset is False
+ if verifies that the file size match with the local file. If None
+ it'll verifies the stash when a file key and offset is given.
+ @type _verify_stash: bool or None
+ @keyword report_success: If the upload was successful it'll print a
+ success message and if ignore_warnings is set to False it'll
+ raise an UploadWarning if a warning occurred. If it's None (default)
+ it'll be True if ignore_warnings is a bool and False otherwise. If
+ it's True or None ignore_warnings must be a bool.
+ @return: It returns True if the upload was successful and False
+ otherwise.
+ @rtype: bool
+ """
+ filename = url = None
+ if '://' in source:
+ url = source
+ else:
+ filename = source
+ return self.site.upload(self, source_filename=filename, source_url=url,
+ **kwargs)
+
wrapper = _ModuleDeprecationWrapper(__name__)
wrapper._add_deprecated_attr('ImagePage', FilePage)
--
To view, visit https://gerrit.wikimedia.org/r/306466
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I2e7113876bc3a150c01701614d13931e1d4819b0
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Lokal Profil <lokal.profil(a)gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: Require site object only for older MediaWiki installations
......................................................................
Require site object only for older MediaWiki installations
The patch in Ifbc3fc0f324c7483f0eba092529a05a8f617ec8c introduced
the need for providing a Site object with WbQuantity to ensure
correct handling of missing error bounds. This affects anyone
working with Wikidata.
This patch changes the behaviour so that Wikidata users can continue
as before and Site objects are only needed for users of older
MediaWiki installations. It also ensures that Wikidata users do not
accidentally go on assuming +/-0 error bounds as default.
See T150210 for discussions.
Bug: T150210
Change-Id: I406db1e86dff772dae7af557859f1458ca87ba5d
---
M pywikibot/__init__.py
M tests/wikibase_tests.py
2 files changed, 4 insertions(+), 2 deletions(-)
Approvals:
Strainu: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 42b93ec..c588b2c 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -609,7 +609,7 @@
warning(
"WbQuantity now expects a 'site' parameter. This is needed to "
"ensure correct handling of error bounds.")
- return True
+ return False
return MediaWikiVersion(site.version()) < MediaWikiVersion('1.29.0-wmf.2')
@staticmethod
diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py
index 8a18771..bad82ba 100644
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -265,10 +265,12 @@
def test_WbQuantity_fromWikibase(self):
"""Test WbQuantity.fromWikibase() instantiating."""
+ repo = self.get_repo()
q = pywikibot.WbQuantity.fromWikibase({u'amount': u'+0.0229',
u'lowerBound': u'0',
u'upperBound': u'1',
- u'unit': u'1'})
+ u'unit': u'1'},
+ site=repo)
# note that the bounds are inputted as INT but are returned as FLOAT
self.assertEqual(q.toWikibase(),
{'amount': '+0.0229', 'lowerBound': '+0.0000',
--
To view, visit https://gerrit.wikimedia.org/r/322672
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I406db1e86dff772dae7af557859f1458ca87ba5d
Gerrit-PatchSet: 3
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Lokal Profil <lokal.profil(a)gmail.com>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinzler(a)wikimedia.de>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <Ladsgroup(a)gmail.com>
Gerrit-Reviewer: Strainu <wiki(a)strainu.ro>
Gerrit-Reviewer: jenkins-bot <>
Build Update for wikimedia/pywikibot-core
-------------------------------------
Build: #3723
Status: Failed
Duration: 1 hour, 8 minutes, and 34 seconds
Commit: 1b2bdf5 (master)
Author: xqt
Message: [bugfix] Fix purgepages() result
linkupdates are only done if the value of the key argument is True or None.
Check for the value first.
Test added.
Bug: T151712
Change-Id: I9367ddf02c782694947c1f452a515cea8971819f
View the changeset: https://github.com/wikimedia/pywikibot-core/compare/f94a8e9b9f14...1b2bdf5f…
View the full build log and details: https://travis-ci.org/wikimedia/pywikibot-core/builds/179203925
--
You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications