jenkins-bot has submitted this change and it was merged.
Change subject: Remove cyclic import between exceptions and data.api
......................................................................
Remove cyclic import between exceptions and data.api
Delay the loading of deprecated symbol 'exceptions.UploadWarning'
which refers to the class 'data.api.UploadWarning'.
Change-Id: I5348ceb79f1440b1d119b730a4eced33de4ff77a
---
M pywikibot/__init__.py
M pywikibot/exceptions.py
M pywikibot/tools/__init__.py
M tests/exceptions_tests.py
4 files changed, 62 insertions(+), 25 deletions(-)
Approvals:
XZise: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 9d6c7d1..0fee2a2 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -38,6 +38,7 @@
# the following are flagged as deprecated on usage
handleArgs,
)
+from pywikibot.data.api import UploadWarning as _UploadWarning
from pywikibot.exceptions import (
Error, InvalidTitle, BadTitle, NoPage, NoMoveTarget, SectionError,
SiteDefinitionError, NoSuchSite, UnknownSite, UnknownFamily,
@@ -53,8 +54,8 @@
)
from pywikibot.tools import PY2, UnicodeMixin, redirect_func
from pywikibot.i18n import translate
-from pywikibot.data.api import UploadWarning
from pywikibot.diff import PatchManager
+
import pywikibot.textlib as textlib
import pywikibot.tools
@@ -757,8 +758,12 @@
wrapper._add_deprecated_attr(
'UserActionRefuse', pywikibot.exceptions._EmailUserError,
warning_message='UserActionRefuse is deprecated; '
- 'use UserRightsError and/or NotEmailableError')
+ 'use UserRightsError and/or NotEmailableError instead.')
wrapper._add_deprecated_attr(
'QuitKeyboardInterrupt', pywikibot.bot.QuitKeyboardInterrupt,
warning_message='pywikibot.QuitKeyboardInterrupt is deprecated; '
- 'use pywikibot.bot.QuitKeyboardInterrupt instead')
+ 'use pywikibot.bot.QuitKeyboardInterrupt instead.')
+wrapper._add_deprecated_attr(
+ 'UploadWarning', _UploadWarning,
+ warning_message='pywikibot.UploadWarning is deprecated; '
+ 'use APISite.upload with a warning handler instead.')
diff --git a/pywikibot/exceptions.py b/pywikibot/exceptions.py
index 64b27d0..1d82980 100644
--- a/pywikibot/exceptions.py
+++ b/pywikibot/exceptions.py
@@ -74,7 +74,7 @@
- FamilyMaintenanceWarning: missing information in family definition
"""
#
-# (C) Pywikibot team, 2008
+# (C) Pywikibot team, 2008-2015
#
# Distributed under the terms of the MIT license.
#
@@ -82,12 +82,14 @@
__version__ = '$Id$'
-import sys
-
-from pywikibot.tools import UnicodeMixin, _NotImplementedWarning
-
-if sys.version_info[0] > 2:
- unicode = str
+from pywikibot.tools import (
+ # __ to avoid conflict with ModuleDeprecationWrapper._deprecated
+ deprecated as __deprecated,
+ ModuleDeprecationWrapper as _ModuleDeprecationWrapper,
+ UnicodeMixin,
+ UnicodeType,
+ _NotImplementedWarning,
+)
class NotImplementedWarning(_NotImplementedWarning):
@@ -179,7 +181,7 @@
@property
def args(self):
"""Expose args."""
- return unicode(self)
+ return UnicodeType(self)
class OtherPageSaveError(PageSaveRelatedError):
@@ -200,7 +202,7 @@
@property
def args(self):
"""Expose args."""
- return unicode(self.reason)
+ return UnicodeType(self.reason)
class NoUsername(Error):
@@ -520,11 +522,7 @@
pass
-import pywikibot.data.api
-import pywikibot.tools
-
-
-(a)pywikibot.tools.deprecated
+@__deprecated
class DeprecatedPageNotFoundError(Error):
"""Page not found (deprecated)."""
@@ -532,7 +530,7 @@
pass
-(a)pywikibot.tools.deprecated
+@__deprecated
class _EmailUserError(UserRightsError, NotEmailableError):
"""Email related error."""
@@ -540,8 +538,12 @@
pass
-wrapper = pywikibot.tools.ModuleDeprecationWrapper(__name__)
-wrapper._add_deprecated_attr('UploadWarning', pywikibot.data.api.UploadWarning)
+wrapper = _ModuleDeprecationWrapper(__name__)
+wrapper._add_deprecated_attr(
+ 'UploadWarning',
+ replacement_name='pywikibot.data.api.UploadWarning',
+ warning_message='pywikibot.exceptions.UploadWarning is deprecated; '
+ 'use APISite.upload with a warning handler instead.')
wrapper._add_deprecated_attr('PageNotFound', DeprecatedPageNotFoundError,
warning_message='{0}.{1} is deprecated, and no '
'longer used by pywikibot; use '
diff --git a/pywikibot/tools/__init__.py b/pywikibot/tools/__init__.py
index f0b7084..61b353d 100644
--- a/pywikibot/tools/__init__.py
+++ b/pywikibot/tools/__init__.py
@@ -1467,6 +1467,8 @@
@type replacement: any
@param replacement_name: The name of the new replaced value. Required
if C{replacement} is not None and it has no __name__ attribute.
+ If it contains a '.', it will be interpreted as a Python dotted
+ object name, and evaluated when the deprecated object is needed.
@type replacement_name: str
@param warning_message: The warning to display, with positional
variables: {0} = module, {1} = attribute name, {2} = replacement.
@@ -1515,6 +1517,20 @@
DeprecationWarning, 2)
if self._deprecated[attr][1]:
return self._deprecated[attr][1]
+ elif '.' in self._deprecated[attr][0]:
+ try:
+ package_name = self._deprecated[attr][0].split('.', 1)[0]
+ module = __import__(package_name)
+ context = {package_name: module}
+ replacement = eval(self._deprecated[attr][0], context)
+ self._deprecated[attr] = (
+ self._deprecated[attr][0],
+ replacement,
+ self._deprecated[attr][2]
+ )
+ return replacement
+ except Exception:
+ pass
return getattr(self._module, attr)
diff --git a/tests/exceptions_tests.py b/tests/exceptions_tests.py
index 853c3c1..5b238d6 100644
--- a/tests/exceptions_tests.py
+++ b/tests/exceptions_tests.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""Tests for exceptions."""
#
-# (C) Pywikibot team, 2014
+# (C) Pywikibot team, 2014-2015
#
# Distributed under the terms of the MIT license.
#
@@ -22,20 +22,34 @@
def test_UploadWarning(self):
"""Test exceptions.UploadWarning is deprecated only."""
- # Accessing from the main package should work fine.
+ # Accessing from the main package should be deprecated.
cls = pywikibot.UploadWarning
- self.assertNoDeprecation()
+
+ self.assertOneDeprecationParts('pywikibot.UploadWarning',
+ 'APISite.upload with a warning handler')
+
e = cls('foo', 'bar')
self.assertIsInstance(e, pywikibot.Error)
self.assertNoDeprecation()
self._reset_messages()
- # But it sholdnt be accessed from the exceptions module.
+ # And it should not be accessed from the exceptions module either.
+ # The first access loads the symbol
cls = pywikibot.exceptions.UploadWarning
self.assertOneDeprecationParts('pywikibot.exceptions.UploadWarning',
- 'pywikibot.data.api.UploadWarning')
+ 'APISite.upload with a warning handler')
+
+ e = cls('foo', 'bar')
+ self.assertIsInstance(e, pywikibot.Error)
+ self.assertNoDeprecation()
+
+ # Check this again because the second time it should be cached
+ cls = pywikibot.exceptions.UploadWarning
+
+ self.assertOneDeprecationParts('pywikibot.exceptions.UploadWarning',
+ 'APISite.upload with a warning handler')
e = cls('foo', 'bar')
self.assertIsInstance(e, pywikibot.Error)
--
To view, visit https://gerrit.wikimedia.org/r/239810
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I5348ceb79f1440b1d119b730a4eced33de4ff77a
Gerrit-PatchSet: 5
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(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: Change "PyWikiBot" to "Pywikibot"
......................................................................
Change "PyWikiBot" to "Pywikibot"
It's like using "WikiPedia"
Change-Id: Ic06ad7716bbd18a697bc934bb9c3d4134d4db716
---
M pywikibot/page.py
M tests/link_tests.py
2 files changed, 3 insertions(+), 3 deletions(-)
Approvals:
Merlijn van Deen: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/page.py b/pywikibot/page.py
index a6069c1..7f949fe 100644
--- a/pywikibot/page.py
+++ b/pywikibot/page.py
@@ -4827,7 +4827,7 @@
except SiteDefinitionError as e:
raise SiteDefinitionError(
u'{0} is not a local page on {1}, and the interwiki prefix '
- '{2} is not supported by PyWikiBot!:\n{3}'.format(
+ '{2} is not supported by Pywikibot!:\n{3}'.format(
self._text, self._site, prefix, e))
else:
t = t[t.index(u":"):].lstrip(u":").lstrip(u" ")
diff --git a/tests/link_tests.py b/tests/link_tests.py
index 804d5af..4d4c2f8 100644
--- a/tests/link_tests.py
+++ b/tests/link_tests.py
@@ -959,7 +959,7 @@
self.assertRaisesRegex(
Error,
'bugzilla:1337 is not a local page on wikipedia:en, and the '
- 'interwiki prefix bugzilla is not supported by PyWikiBot!',
+ 'interwiki prefix bugzilla is not supported by Pywikibot!',
link.parse)
def test_other_wiki_prefix(self):
@@ -968,7 +968,7 @@
self.assertRaisesRegex(
Error,
'bulba:this-will-never-work is not a local page on wikipedia:en, '
- 'and the interwiki prefix bulba is not supported by PyWikiBot!',
+ 'and the interwiki prefix bulba is not supported by Pywikibot!',
link.parse)
--
To view, visit https://gerrit.wikimedia.org/r/240338
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ic06ad7716bbd18a697bc934bb9c3d4134d4db716
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(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: Dont overwrite tools.debug
......................................................................
Dont overwrite tools.debug
d7d7a146 introduced pywikibot.logging, with pywikibot.tools
importing pywikibot.logging for `debug`.
pywikibot.bot.init_handlers previously set pywikibot.tools.debug,
which became unnecessary after d7d7a146.
Alter the use of pywikibot.debug to use debug, so it isnt unused.
Bug: T113161
Change-Id: Ia319abf3745924e0ec89ecbb4a7477aaffc0584f
---
M pywikibot/bot.py
1 file changed, 1 insertion(+), 3 deletions(-)
Approvals:
John Vandenberg: Looks good to me, but someone else must approve
XZise: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/bot.py b/pywikibot/bot.py
index 25ed2b0..a0589ab 100644
--- a/pywikibot/bot.py
+++ b/pywikibot/bot.py
@@ -272,8 +272,6 @@
_handlers_initialized = True
- pywikibot.tools.debug = debug
-
writelogheader()
@@ -953,7 +951,7 @@
showHelp()
sys.exit(0)
- pywikibot.debug(u"handle_args() completed.", _logger)
+ debug('handle_args() completed.', _logger)
return nonGlobalArgs
--
To view, visit https://gerrit.wikimedia.org/r/239643
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ia319abf3745924e0ec89ecbb4a7477aaffc0584f
Gerrit-PatchSet: 4
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: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: [FIX] color_format: Only handle unicode strings
......................................................................
[FIX] color_format: Only handle unicode strings
When using `unicode.format` it does return a `unicode` instance, but
`color_format` is based on Python's `Formatter` class which doesn't apply that
rule.
So it needs to workaround the issue that Python's `Formatter` will return the
`bytes` representation of an object when there is no further specification
(aka nothing after the colon). The default implementation will also return
`bytes` when there is no literal text and it might cause `UnicodeDecodeError`s
when there is literal text and the bytes representation does use non-ASCII
characters.
Bug: T113411
Change-Id: I0f8e0f1ac3e64c57918d99e9716c486270a87766
---
M pywikibot/tools/formatter.py
M tests/tools_formatter_tests.py
2 files changed, 69 insertions(+), 10 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/tools/formatter.py b/pywikibot/tools/formatter.py
index 151e4d9..ae9c530 100644
--- a/pywikibot/tools/formatter.py
+++ b/pywikibot/tools/formatter.py
@@ -15,6 +15,7 @@
from string import Formatter
from pywikibot.logging import output
+from pywikibot.tools import UnicodeType
from pywikibot.userinterfaces.terminal_interface_base import colors
@@ -103,11 +104,41 @@
if previous_literal:
yield previous_literal, None, None, None
+ def _vformat(self, *args, **kwargs):
+ """
+ Override original `_vformat` to prevent that it changes into `bytes`.
+
+ The original `_vformat` is returning `bytes` under certain
+ curcumstances. It happens when the `format_string` is empty, when there
+ is no literal text around it or when the field value is not a `unicode`
+ already.
+
+ @rtype: unicode
+ """
+ result = super(_ColorFormatter, self)._vformat(*args, **kwargs)
+ if not isinstance(result, UnicodeType):
+ assert result == b''
+ result = '' # This is changing it into a unicode
+ return result
+
def vformat(self, format_string, args, kwargs):
- """Return the normal format result but verify no colors are keywords."""
+ """
+ Return the normal format result but verify no colors are keywords.
+
+ @param format_string: The format template string
+ @type format_string: unicode
+ @param args: The positional field values
+ @type args: sequence
+ @param kwargs: The named field values
+ @type kwargs: dict
+ @return: The formatted string
+ @rtype: unicode
+ """
if self.colors.intersection(kwargs): # kwargs use colors
raise ValueError('Keyword argument(s) use valid color(s): ' +
'", "'.join(self.colors.intersection(kwargs)))
+ if not isinstance(format_string, UnicodeType):
+ raise TypeError('expected str, got {0}'.format(type(format_string)))
return super(_ColorFormatter, self).vformat(format_string, args,
kwargs)
@@ -118,5 +149,10 @@
It is automatically adding \03 in front of color fields so it's
unnecessary to add them manually. Any other \03 in the text is disallowed.
+
+ @param text: The format template string
+ @type text: unicode
+ @return: The formatted string
+ @rtype: unicode
"""
return _ColorFormatter().format(text, *args, **kwargs)
diff --git a/tests/tools_formatter_tests.py b/tests/tools_formatter_tests.py
index a441e35..bd3a2df 100644
--- a/tests/tools_formatter_tests.py
+++ b/tests/tools_formatter_tests.py
@@ -10,6 +10,7 @@
__version__ = '$Id$'
#
from pywikibot.tools import formatter
+from pywikibot.tools import UnicodeMixin
from tests.aspects import unittest, TestCase
@@ -35,20 +36,31 @@
"""Test color_format function in bot module."""
+ class DummyUnicode(UnicodeMixin):
+
+ def __unicode__(self):
+ return 'ä'
+
net = False
+
+ def assert_format(self, format_string, expected, *args, **kwargs):
+ """Assert that color_format returns the expected string and type."""
+ result = formatter.color_format(format_string, *args, **kwargs)
+ self.assertEqual(result, expected)
+ self.assertIsInstance(result, type(expected))
def test_no_colors(self):
"""Test without colors in template string."""
- self.assertEqual(formatter.color_format('42'), '42')
- self.assertEqual(formatter.color_format('{0}', 42), '42')
- self.assertEqual(formatter.color_format('{ans}', ans=42), '42')
+ self.assert_format('', '')
+ self.assert_format('42', '42')
+ self.assert_format('{0}', '42', 42)
+ self.assert_format('before {0} after', 'before 42 after', 42)
+ self.assert_format('{ans}', '42', ans=42)
def test_colors(self):
"""Test with colors in template string."""
- self.assertEqual(formatter.color_format('{0}{black}', 42),
- '42\03{black}')
- self.assertEqual(formatter.color_format('{ans}{black}', ans=42),
- '42\03{black}')
+ self.assert_format('{0}{black}', '42\03{black}', 42)
+ self.assert_format('{ans}{black}', '42\03{black}', ans=42)
self.assertRaisesRegex(
ValueError, r'.*conversion.*', formatter.color_format,
'{0}{black!r}', 42)
@@ -58,8 +70,7 @@
def test_marker(self):
r"""Test that the \03 marker is only allowed in front of colors."""
- self.assertEqual(formatter.color_format('{0}\03{black}', 42),
- '42\03{black}')
+ self.assert_format('{0}\03{black}', '42\03{black}', 42)
# literal before a normal field
self.assertRaisesRegex(
ValueError, r'.*\\03', formatter.color_format,
@@ -74,6 +85,18 @@
self.assertRaises(ValueError,
formatter.color_format, '{aqua}{black}', aqua=42)
+ def test_non_ascii(self):
+ """Test non-ASCII replacements."""
+ self.assert_format('{0}', 'ä', 'ä')
+ self.assert_format('{black}{0}', '\03{black}ä', 'ä')
+ self.assert_format('{0}', 'ä', self.DummyUnicode())
+ self.assert_format('{black}{0}', '\03{black}ä', self.DummyUnicode())
+
+ def test_bytes_format(self):
+ """Test that using `bytes` is not allowed."""
+ self.assertRaises(TypeError, formatter.color_format, b'{0}', 'a')
+ self.assertRaises(TypeError, formatter.color_format, b'{black}{0}', 'a')
+
if __name__ == '__main__':
try:
--
To view, visit https://gerrit.wikimedia.org/r/240291
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I0f8e0f1ac3e64c57918d99e9716c486270a87766
Gerrit-PatchSet: 2
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: jenkins-bot <>