jenkins-bot has submitted this change and it was merged.
Change subject: [FEAT] Raise QuitKeyboardInterrupt on Ctrl+C and Quit/q
......................................................................
[FEAT] Raise QuitKeyboardInterrupt on Ctrl+C and Quit/q
Whenever 'input()' is used all KeyboardInterrupts are changed into
QuitKeyboardInterrupts. As 'inputChoice()' uses 'input()' as well
this applies also to 'inputChoice()'.
Also sorted the inputs and didn't rename 'pywikibot' to 'wikipedia'.
Change-Id: Ib3ef5aef5d0f7ab7338a2ec9dfdf7592c4067923
---
M pywikibot/bot.py
M pywikibot/userinterfaces/terminal_interface_base.py
2 files changed, 15 insertions(+), 16 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/bot.py b/pywikibot/bot.py
index 1011d85..2417922 100644
--- a/pywikibot/bot.py
+++ b/pywikibot/bot.py
@@ -909,10 +909,6 @@
pywikibot.output('\nUser quit %s bot run...' %
self.__class__.__name__)
except KeyboardInterrupt:
- # TODO: If the ^C occurred during an input()
- # it should be handled as a QuitKeyboardInterrupt
- # as developers shouldnt need a backtrace to find
- # where the input() code is.
if config.verbose_output:
raise
else:
diff --git a/pywikibot/userinterfaces/terminal_interface_base.py b/pywikibot/userinterfaces/terminal_interface_base.py
index 411cc31..c1363e1 100755
--- a/pywikibot/userinterfaces/terminal_interface_base.py
+++ b/pywikibot/userinterfaces/terminal_interface_base.py
@@ -9,10 +9,10 @@
from . import transliteration
import re
import sys
-import pywikibot as wikipedia
+import logging
+import pywikibot
from pywikibot import config
from pywikibot.bot import VERBOSE, INFO, STDOUT, INPUT, WARNING
-import logging
transliterator = transliteration.transliterator(config.console_encoding)
@@ -185,11 +185,14 @@
sys.stdout.write('\07')
# TODO: make sure this is logged as well
self.output(question + ' ')
- if password:
- import getpass
- text = getpass.getpass('')
- else:
- text = self._raw_input()
+ try:
+ if password:
+ import getpass
+ text = getpass.getpass('')
+ else:
+ text = self._raw_input()
+ except KeyboardInterrupt:
+ raise pywikibot.QuitKeyboardInterrupt()
text = unicode(text, self.encoding)
return text
@@ -245,20 +248,20 @@
"""Show the user a CAPTCHA image and return the answer."""
try:
import webbrowser
- wikipedia.output(u'Opening CAPTCHA in your web browser...')
+ pywikibot.output(u'Opening CAPTCHA in your web browser...')
if webbrowser.open(url):
- return wikipedia.input(
+ return pywikibot.input(
u'What is the solution of the CAPTCHA that is shown in '
u'your web browser?')
else:
raise
except:
- wikipedia.output(u'Error in opening web browser: %s'
+ pywikibot.output(u'Error in opening web browser: %s'
% sys.exc_info()[0])
- wikipedia.output(
+ pywikibot.output(
u'Please copy this url to your web browser and open it:\n %s'
% url)
- return wikipedia.input(
+ return pywikibot.input(
u'What is the solution of the CAPTCHA at this url ?')
def argvu(self):
--
To view, visit https://gerrit.wikimedia.org/r/155768
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ib3ef5aef5d0f7ab7338a2ec9dfdf7592c4067923
Gerrit-PatchSet: 3
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: Mpaa <mpaa.wiki(a)gmail.com>
Gerrit-Reviewer: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: Remove reference to missing Site.getcurrenttime
......................................................................
Remove reference to missing Site.getcurrenttime
Site.getcurrenttime exists in core but not compat.
Change-Id: Ia2f0d52921cb4da53133e81a8c2b4a4939db796f
---
M pywikibot/support.py
1 file changed, 0 insertions(+), 3 deletions(-)
Approvals:
Xqt: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/support.py b/pywikibot/support.py
index e6db56b..072bb25 100644
--- a/pywikibot/support.py
+++ b/pywikibot/support.py
@@ -31,9 +31,6 @@
Use Timestamp.fromISOformat() and Timestamp.fromtimestampformat() to
create Timestamp objects from Mediawiki string formats.
- Use Site.getcurrenttime() for the current time; this is more reliable
- than using Timestamp.utcnow().
-
"""
mediawikiTSFormat = "%Y%m%d%H%M%S"
ISO8601Format = "%Y-%m-%dT%H:%M:%SZ"
--
To view, visit https://gerrit.wikimedia.org/r/155548
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ia2f0d52921cb4da53133e81a8c2b4a4939db796f
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/compat
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(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: Cherrypick: select and apply diffs between texts
......................................................................
Cherrypick: select and apply diffs between texts
Display diffs, allow their selection and apply approved diffs.
Return text obtained by applying only approved diffs.
Change-Id: I11b5f36b2416f3f9a9209141d9df3fab483004b8
---
A pywikibot/diff.py
1 file changed, 337 insertions(+), 0 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/diff.py b/pywikibot/diff.py
new file mode 100644
index 0000000..490b0df
--- /dev/null
+++ b/pywikibot/diff.py
@@ -0,0 +1,337 @@
+# -*- coding: utf-8 -*-
+"""
+User-interface related functions
+"""
+#
+# (C) Pywikibot team, 2014
+#
+# Distributed under the terms of the MIT license.
+#
+__version__ = '$Id$'
+
+
+import difflib
+import itertools
+
+import pywikibot
+
+
+class Hunk(object):
+ """One change hunk between a and b.
+
+ a and b: two sequences of lines.
+ grouped_opcode: list of 5-tuples describing how to turn a into b.
+ it has the same format as returned by difflib.get_opcodes().
+
+ Note: parts of this code are taken from by difflib.get_grouped_opcodes().
+
+ """
+
+ APPR = 1
+ NOT_APPR = -1
+ PENDING = 0
+
+ def __init__(self, a, b, grouped_opcode):
+ self.a = a
+ self.b = b
+ self.group = grouped_opcode
+ self.header = u''
+ self.colors = {
+ '+': 'lightgreen',
+ '-': 'lightred',
+ }
+
+ self.diff = list(self.create_diff())
+ self.diff_plain_text = u''.join(self.diff)
+ self.diff_text = u''.join(self.format_diff())
+
+ first, last = self.group[0], self.group[-1]
+ self.a_rng = (first[1], last[2])
+ self.b_rng = (first[3], last[4])
+
+ self.header = self.get_header()
+ self.diff_plain_text = u'%s\n%s' % (self.header, self.diff_plain_text)
+ self.diff_text = u'%s' % self.diff_text
+
+ self.reviewed = self.PENDING
+
+ def get_header(self):
+ """Provide header of unified diff."""
+
+ a_rng = difflib._format_range_unified(*self.a_rng)
+ b_rng = difflib._format_range_unified(*self.b_rng)
+ return '@@ -{} +{} @@{}'.format(a_rng, b_rng, '\n')
+
+ def create_diff(self):
+ """Generator of diff text for this hunk, without formatting."""
+
+ # make sure each line ends with '\n' to prevent
+ # behaviour like http://bugs.python.org/issue2142
+ def check_line(l):
+ if not l.endswith('\n'):
+ return l + '\n'
+ return l
+
+ for tag, i1, i2, j1, j2 in self.group:
+ if tag == 'equal':
+ for line in self.a[i1:i2]:
+ yield ' ' + check_line(line)
+ if tag in ('delete'):
+ for line in self.a[i1:i2]:
+ yield '-' + check_line(line)
+ if tag in ('insert'):
+ for line in self.b[j1:j2]:
+ yield '+' + check_line(line)
+ if tag in ('replace'):
+ for line in difflib.ndiff(self.a[i1:i2], self.b[j1:j2]):
+ yield check_line(line)
+
+ def format_diff(self):
+ """Color diff lines."""
+
+ diff = iter(self.diff)
+
+ l1, l2 = '', next(diff)
+ for line in diff:
+ l1, l2 = l2, line
+ # do not show lines starting with '?'.
+ if l1.startswith('?'):
+ continue
+ if l2.startswith('?'):
+ yield self.color_line(l1, l2)
+ else:
+ yield self.color_line(l1)
+
+ # handle last line
+ if not l2.startswith('?'):
+ yield self.color_line(l2)
+
+ def color_line(self, line, line_ref=None):
+ """Color line characters.
+
+ If line_ref is None, the whole line is colored.
+ If line_ref[i] is not blank, line[i] is colored.
+ Color depends if line starts with +/-.
+
+ line: string
+ line_ref: string.
+
+ """
+
+ color = line[0]
+
+ if line_ref is None:
+ if color in self.colors:
+ colored_line = '\03{%s}%s\03{default}' % (self.colors[color], line)
+ return colored_line
+ else:
+ return line
+
+ colored_line = u''
+ state = 'Close'
+ for char, char_ref in itertools.izip_longest(line, line_ref.strip(), fillvalue=' '):
+ char_tagged = char
+ if state == 'Close':
+ if char_ref != ' ':
+ char_tagged = '\03{%s}%s' % (self.colors[color], char)
+ state = 'Open'
+ elif state == 'Open':
+ if char_ref == ' ':
+ char_tagged = '\03{default}%s' % char
+ state = 'Close'
+ colored_line += char_tagged
+
+ if state == 'Open':
+ colored_line += '\03{default}'
+
+ return colored_line
+
+ def apply(self):
+ """Turn a into b for this hunk."""
+ return self.b[self.b_rng[0]:self.b_rng[1]]
+
+ def __str__(self):
+ return u''.join(self.diff_plain_text)
+
+ def __repr__(self):
+ """Return a reconstructable representation."""
+ # TODO
+ return '%s(a, b, %s)' \
+ % (self.__class__.__name__, self.group)
+
+
+class PatchManager(object):
+ """Apply patches to text_a to obtain a new text.
+
+ If all hunks are approved, text_b will be obtained.
+ letter by letter.
+
+ """
+
+ def __init__(self, text_a, text_b, n=0, by_letter=False):
+ """Constructor.
+
+ text_a: string
+ text_b: string
+ n: int, line of context as defined in difflib.get_grouped_opcodes().
+ by_letter: if text_a and text_b are single lines, comparison can be done
+
+ """
+
+ if '\n' in text_a or '\n' in text_b:
+ self.a = text_a.splitlines(1)
+ self.b = text_b.splitlines(1)
+ else:
+ if by_letter:
+ self.a = text_a
+ self.b = text_b
+ else:
+ self.a = text_a.splitlines(1)
+ self.b = text_b.splitlines(1)
+
+ # groups and hunk have same order (one hunk correspond to one group).
+ s = difflib.SequenceMatcher(None, self.a, self.b)
+ self.groups = list(s.get_grouped_opcodes(n))
+ self.hunks = [Hunk(self.a, self.b, group) for group in self.groups]
+ # blocks are a superset of hunk, as include also parts not
+ # included in any hunk.
+ self.blocks = self.get_blocks()
+
+ def get_blocks(self):
+ """Return list with blocks of indexes which compose a and, where applicable, b.
+
+ Format of each block:
+ [-1, (i1, i2), (-1, -1)] -> block a[i1:i2] does not change from a to b
+ then is there is no corresponding hunk.
+ [hunk index, (i1, i2), (j1, j2)] -> block a[i1:i2] becomes b[j1:j2]
+
+ """
+
+ blocks = []
+ i2 = 0
+ for hunk_idx, group in enumerate(self.groups):
+
+ first, last = group[0], group[-1]
+ i1, prev_i2, i2 = first[1], i2, last[2]
+
+ # there is a section of unchanged text before this hunk.
+ if prev_i2 < i1:
+ rng = (-1, (prev_i2, i1), (-1, -1))
+ blocks.append(rng)
+
+ rng = (hunk_idx, (first[1], last[2]), (first[3], last[4]))
+ blocks.append(rng)
+
+ # there is a section of unchanged text at the end of a, b.
+ if i2 < len(self.a):
+ rng = (-1, (last[2], len(self.a)), (-1, -1))
+ blocks.append(rng)
+
+ return blocks
+
+ def review_hunks(self):
+ "Review hunks."
+
+ help_msg = ['y -> accept this hunk',
+ 'n -> do not accept this hunk',
+ 's -> do not accept this hunk and stop reviewing',
+ 'a -> accept this hunk and all other pending',
+ 'r -> review later',
+ 'h -> help',
+ ]
+
+ question = 'Accept this hunk?'
+ answers = ['yes', 'no', 'stop', 'all', 'review', 'help']
+ hotkeys = ['y', 'n', 's', 'a', 'r', 'h']
+ actions = {'y': Hunk.APPR,
+ 'n': Hunk.NOT_APPR,
+ 's': Hunk.NOT_APPR,
+ 'a': Hunk.APPR,
+ 'r': Hunk.PENDING,
+ }
+
+ pending = [h for h in self.hunks if h.reviewed == h.PENDING]
+
+ while pending:
+
+ hunk = pending.pop(0)
+
+ pywikibot.output(hunk.header + hunk.diff_text)
+ choice = pywikibot.inputChoice(question, answers, hotkeys, default='r')
+
+ if choice in actions.keys():
+ hunk.reviewed = actions[choice]
+ if choice == 's':
+ while pending:
+ hunk = pending.pop(0)
+ hunk.reviewed = hunk.NOT_APPR
+ break
+ elif choice == 'a':
+ while pending:
+ hunk = pending.pop(0)
+ hunk.reviewed = hunk.APPR
+ break
+ elif choice == 'h':
+ pywikibot.output(u'\03{purple}%s\03{default}' % u'\n'.join(help_msg))
+ pending.insert(0, hunk)
+ elif choice == 'r':
+ pending.append(hunk)
+
+ return
+
+ def apply(self):
+ """Apply changes. If there are undecided changes, ask to review."""
+
+ if any(h.reviewed == h.PENDING for h in self.hunks):
+ pywikibot.output("There are unreviewed hunks.\n"
+ "Please review them before proceeding.\n")
+ self.review_hunks()
+
+ l_text = []
+ for hunk_idx, (i1, i2), (j1, j2) in self.blocks:
+ # unchanged text.
+ if hunk_idx < 0:
+ l_text.extend(self.a[i1:i2])
+ # changed text; check if hunk is approved.
+ else:
+ hunk = self.hunks[hunk_idx]
+ if hunk.reviewed == hunk.APPR:
+ l_text.extend(self.b[j1:j2])
+ else:
+ l_text.extend(self.a[i1:i2])
+
+ # Make a sanity check in case all are approved.
+ if all(h.reviewed == h.APPR for h in self.hunks):
+ assert u''.join(l_text) == u''.join(self.b)
+ return l_text
+
+
+def cherry_pick(oldtext, newtext, n=0, by_letter=False):
+ """Propose a list of changes for approval.
+
+ Text with approved changes will be returned.
+ n: int, line of context as defined in difflib.get_grouped_opcodes().
+ by_letter: if text_a and text_b are single lines, comparison can be done
+
+ """
+
+ patch = PatchManager(oldtext, newtext, n=n, by_letter=by_letter)
+ pywikibot.output('\03{{lightpurple}}\n{:*^50}\03{{default}}\n'.format(' ALL CHANGES '))
+
+ for hunk in patch.hunks:
+ pywikibot.output(hunk.diff_text)
+ pywikibot.output('\03{{lightpurple}}\n{:*^50}\03{{default}}\n'.format(' REVIEW CHANGES '))
+
+ text_list = patch.apply()
+ pywikibot.output('\03{{lightpurple}}\n{:*^50}\03{{default}}\n'.format(' APPROVED CHANGES '))
+
+ if any(hunk.reviewed == hunk.APPR for hunk in patch.hunks):
+ for hunk in patch.hunks:
+ if hunk.reviewed == hunk.APPR:
+ pywikibot.output(hunk.diff_text)
+ else:
+ pywikibot.output('\03{{lightpurple}}{:^50}\03{{default}}'.format('None.'))
+
+ text = ''.join(text_list)
+
+ return text
--
To view, visit https://gerrit.wikimedia.org/r/154957
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I11b5f36b2416f3f9a9209141d9df3fab483004b8
Gerrit-PatchSet: 3
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Mpaa <mpaa.wiki(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: Mpaa <mpaa.wiki(a)gmail.com>
Gerrit-Reviewer: Ricordisamoa <ricordisamoa(a)openmailbox.org>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: Wikidata is now its own client
......................................................................
Wikidata is now its own client
Update Wikidata family configuration.
Existing tests need to be updated as they verified that the Wikidata
site was not a client, which is no longer true.
Change-Id: If98313a6ca79d660d68b9cfc5a990d68218430ec
---
M pywikibot/families/wikidata_family.py
M tests/wikibase_tests.py
2 files changed, 25 insertions(+), 21 deletions(-)
Approvals:
John Vandenberg: Looks good to me, but someone else must approve
Ladsgroup: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/families/wikidata_family.py b/pywikibot/families/wikidata_family.py
index cccc614..2e33e5b 100644
--- a/pywikibot/families/wikidata_family.py
+++ b/pywikibot/families/wikidata_family.py
@@ -17,14 +17,17 @@
}
def shared_data_repository(self, code, transcluded=False):
- """Always return a repository tupe. This enables testing whether
- the site object is the repository itself, see Site.is_data_repository()
-
"""
- if transcluded:
- return (None, None)
- else:
- return (code, self.name)
+ Indicate Wikidata is both a repository and its own client.
+
+ Until 20 August 2014, Wikidata was only a data repository,
+ and this method only returned a tuple with data if
+ transcluded was False.
+
+ On that date, the software was enhanced so that Wikidata
+ could store sitelinks to itself.
+ """
+ return (code, self.name)
def calendarmodel(self, code):
"""Default calendar model for WbTime datatype"""
diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py
index 0f1cba9..05dd97b 100644
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -127,21 +127,23 @@
'species.*no transcluded data',
self.wdp.data_item)
- # test.wikidata does not have a data repository.
- self.wdp = pywikibot.ItemPage(wikidatatest, 'Q6')
- self.assertRaises(pywikibot.WikiBaseError,
- pywikibot.ItemPage.fromPage, self.wdp)
+ def test_own_client(self):
+ """Test that a data repository family can be its own client."""
+ # Note: these tests do not yet verify that pywikibot can
+ # utilise this Wikibase configuration, as it is not yet
+ # working correctly on Wikidata.
- # The main Wikidata also does not have a data repository.
- # It is a data repository, but no pages on Wikidata have
- # a linked page.
- self.wdp = pywikibot.ItemPage(wikidata, 'Q60')
- self.assertRaises(pywikibot.WikiBaseError,
- pywikibot.ItemPage.fromPage, self.wdp)
+ # The main Wikidata is its own client.
+ self.wdp = pywikibot.ItemPage(wikidata,
+ wikidata.siteinfo['mainpage'])
+ item = pywikibot.ItemPage.fromPage(self.wdp)
+ del item
- self.wdp = pywikibot.Page(wikidata, 'Main Page', ns=4)
- self.assertRaises(pywikibot.WikiBaseError,
- pywikibot.ItemPage.fromPage, self.wdp)
+ # test.wikidata is also
+ self.wdp = pywikibot.ItemPage(wikidatatest,
+ wikidatatest.siteinfo['mainpage'])
+ item = pywikibot.ItemPage.fromPage(self.wdp)
+ del item
class TestItemLoad(PywikibotTestCase):
@@ -413,7 +415,6 @@
def test_page_methods(self):
"""Test ItemPage methods inherited from superclass Page."""
self.wdp = pywikibot.ItemPage(wikidatatest, 'Q6')
- self.assertRaises(pywikibot.WikiBaseError, self.wdp.data_item)
self.assertRaises(pywikibot.PageNotSaved, self.wdp.save)
self.wdp.previousRevision()
self.assertEquals(self.wdp.langlinks(), [])
--
To view, visit https://gerrit.wikimedia.org/r/155225
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: If98313a6ca79d660d68b9cfc5a990d68218430ec
Gerrit-PatchSet: 2
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(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: [FEAT] Add deprecation warnings for textlib/deprecation redirects
......................................................................
[FEAT] Add deprecation warnings for textlib/deprecation redirects
It's adding a function which dynamically can create a redirect to
another function and warn because of deprecation when the
redirected function is executed. It works similar to the
@deprecated decorator but doesn't require the old function.
All functions which from 'textlib' which were simply redirected
from 'pywikibot' to the 'textlib' module are created with this
function. Also 'deprecated' and 'deprecate_arg' are marked as
deprecated too.
Change-Id: I69dbf351c22fd0caacbf047ae38aca067f8cef96
---
M pywikibot/__init__.py
M pywikibot/tools.py
2 files changed, 79 insertions(+), 20 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 0d13cdf..6804291 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -41,21 +41,24 @@
CaptchaError, SpamfilterError, CircularRedirect,
WikiBaseError, CoordinateGlobeUnknownException,
)
-from pywikibot.textlib import (
- unescape, replaceExcept, removeDisabledParts, removeHTMLParts,
- isDisabled, interwikiFormat, interwikiSort,
- getLanguageLinks, replaceLanguageLinks,
- removeLanguageLinks, removeLanguageLinksAndSeparator,
- getCategoryLinks, categoryFormat, replaceCategoryLinks,
- removeCategoryLinks, removeCategoryLinksAndSeparator,
- replaceCategoryInPlace, compileLinkR, extract_templates_and_params,
-)
-from pywikibot.tools import UnicodeMixin, deprecated, deprecate_arg
+from pywikibot.tools import UnicodeMixin, redirect_func
from pywikibot.i18n import translate
from pywikibot.data.api import UploadWarning
+import pywikibot.textlib as textlib
+import pywikibot.tools
+
+textlib_methods = (
+ 'unescape', 'replaceExcept', 'removeDisabledParts', 'removeHTMLParts',
+ 'isDisabled', 'interwikiFormat', 'interwikiSort',
+ 'getLanguageLinks', 'replaceLanguageLinks',
+ 'removeLanguageLinks', 'removeLanguageLinksAndSeparator',
+ 'getCategoryLinks', 'categoryFormat', 'replaceCategoryLinks',
+ 'removeCategoryLinks', 'removeCategoryLinksAndSeparator',
+ 'replaceCategoryInPlace', 'compileLinkR', 'extract_templates_and_params',
+)
__all__ = (
- 'config', 'ui', 'UnicodeMixin', 'translate', 'deprecated', 'deprecate_arg',
+ 'config', 'ui', 'UnicodeMixin', 'translate',
'Page', 'FilePage', 'ImagePage', 'Category', 'Link', 'User',
'ItemPage', 'PropertyPage', 'Claim', 'TimeStripper',
'html2unicode', 'url2unicode', 'unicode2html',
@@ -67,17 +70,24 @@
'PageRelatedError', 'IsRedirectPage', 'IsNotRedirectPage',
'PageNotSaved', 'UploadWarning', 'LockedPage', 'EditConflict',
'ServerError', 'FatalServerError', 'Server504Error',
- 'CaptchaError', 'SpamfilterError', 'CircularRedirect',
+ 'CaptchaError', 'SpamfilterError', 'CircularRedirect',
'WikiBaseError', 'CoordinateGlobeUnknownException',
- 'unescape', 'replaceExcept', 'removeDisabledParts', 'removeHTMLParts',
- 'isDisabled', 'interwikiFormat', 'interwikiSort',
- 'getLanguageLinks', 'replaceLanguageLinks',
- 'removeLanguageLinks', 'removeLanguageLinksAndSeparator',
- 'getCategoryLinks', 'categoryFormat', 'replaceCategoryLinks',
- 'removeCategoryLinks', 'removeCategoryLinksAndSeparator',
- 'replaceCategoryInPlace', 'compileLinkR', 'extract_templates_and_params',
'QuitKeyboardInterrupt',
)
+# flake8 is unable to detect concatenation in the same operation
+# like:
+# ) + textlib_methods
+# so instead use this trick
+globals()['__all__'] = __all__ + textlib_methods
+
+for _name in textlib_methods:
+ target = getattr(textlib, _name)
+ wrapped_func = redirect_func(target)
+ globals()[_name] = wrapped_func
+
+
+deprecated = redirect_func(pywikibot.tools.deprecated)
+deprecate_arg = redirect_func(pywikibot.tools.deprecate_arg)
class Timestamp(datetime.datetime):
@@ -491,7 +501,7 @@
link_regex = re.compile(r'\[\[(?P<title>[^\]|[<>{}]*)(\|.*?)?\]\]')
-@deprecated("comment parameter for page saving method")
+(a)pywikibot.tools.deprecated("comment parameter for page saving method")
def setAction(s):
"""Set a summary to use for changed page submissions"""
config.default_edit_summary = s
diff --git a/pywikibot/tools.py b/pywikibot/tools.py
index 462b5ef..fb8628f 100644
--- a/pywikibot/tools.py
+++ b/pywikibot/tools.py
@@ -314,6 +314,55 @@
return decorator
+def redirect_func(target, source_module=None, target_module=None):
+ """
+ Return a function which can be used to redirect to 'target'.
+
+ It also acts like marking that function deprecated and copies all
+ parameters.
+
+ @param target: The targeted function which is to be executed.
+ @type target: callable
+ @param source_module: The module of the old function. If '.' defaults
+ to target_module. If 'None' (default) it tries to guess it from the
+ executing function.
+ @type source_module: basestring
+ @param target_module: The module of the target function. If
+ 'None' (default) it tries to get it from the target. Might not work
+ with nested classes.
+ @type target_module: basestring
+ @return: A new function which adds a warning prior to each execution.
+ @rtype: callable
+ """
+ class Wrapper(object):
+ def __init__(self, function, source, target):
+ self._function = function
+ self.parameters = {'new': function.func_name,
+ 'target': target,
+ 'source': source}
+ self.warning = ('{source}{new} is DEPRECATED, use {target}{new} '
+ 'instead.').format(**self.parameters)
+
+ def call(self, *a, **kw):
+ warning(self.warning)
+ return self._function(*a, **kw)
+
+ if target_module is None:
+ target_module = target.__module__
+ if hasattr(target, 'im_class'):
+ target_module += '.' + target.im_class.__name__
+ if target_module and target_module[-1] != '.':
+ target_module += '.'
+ if source_module is '.':
+ source_module = target_module
+ elif source_module and source_module[-1] != '.':
+ source_module += '.'
+ else:
+ source_module = (sys._getframe(1).f_code.co_filename.rsplit("/", 1)[0]
+ .replace("/", ".") + ".")
+ return Wrapper(target, source_module, target_module).call
+
+
if __name__ == "__main__":
def _test():
import doctest
--
To view, visit https://gerrit.wikimedia.org/r/155159
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I69dbf351c22fd0caacbf047ae38aca067f8cef96
Gerrit-PatchSet: 8
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: Dont use deprecated Page() defaultNamespace param
......................................................................
Dont use deprecated Page() defaultNamespace param
Running script nowcommons causes the following deprecation notices to appear
twice on startup:
WARNING: defaultNamespace argument of __init__ is deprecated; use ns instead.
Removing it from the nowcommons and blockreview scripts.
Change-Id: If8ca72d62f85577e306f4fe0be490632e69f805e
---
M scripts/blockreview.py
M scripts/nowcommons.py
2 files changed, 3 insertions(+), 3 deletions(-)
Approvals:
Mpaa: Looks good to me, approved
jenkins-bot: Verified
diff --git a/scripts/blockreview.py b/scripts/blockreview.py
index 8cba078..3e1be78 100644
--- a/scripts/blockreview.py
+++ b/scripts/blockreview.py
@@ -94,7 +94,7 @@
try:
genPage = pywikibot.Page(self.site,
self.unblock_tpl[self.site.code],
- defaultNamespace=10)
+ ns=10)
except KeyError:
pywikibot.error(u'Language "%s" not supported by this bot.'
% self.site.code)
@@ -254,7 +254,7 @@
if 'bot' not in user['groups']:
# yield the sysop talkpage
yield pywikibot.Page(self.site, user['name'],
- defaultNamespace=3)
+ ns=3)
def load(self, page):
"""Loads the given page, does some changes, and saves it."""
diff --git a/scripts/nowcommons.py b/scripts/nowcommons.py
index 14c3f06..4e5338f 100644
--- a/scripts/nowcommons.py
+++ b/scripts/nowcommons.py
@@ -265,7 +265,7 @@
gen = self.useHashGenerator()
else:
nowCommonsTemplates = [pywikibot.Page(self.site, title,
- defaultNamespace=10)
+ ns=10)
for title in self.ncTemplates()]
gens = [pg.ReferringPageGenerator(t, followRedirects=True,
onlyTemplateInclusion=True)
--
To view, visit https://gerrit.wikimedia.org/r/155604
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: If8ca72d62f85577e306f4fe0be490632e69f805e
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: Mpaa <mpaa.wiki(a)gmail.com>
Gerrit-Reviewer: jenkins-bot <>