jenkins-bot has submitted this change and it was merged.
Change subject: [IMPR] Make LogEntryFactory logtypes public
......................................................................
[IMPR] Make LogEntryFactory logtypes public
- rename LogEntryFactory._logtypes to LogEntryFactory.logtypes
in order to make them public
- add a _logtypes class method to deprecate the old class attribute
- use a new decorator 'classproperty' to get property access to the
_logtypes method
- create a new classproperty class to realize the classproperty decorator
and test it
- rename all old attributes to the new one
Change-Id: I5467a59beb93372a89426b6bfaaca4cd38e71e57
---
M pywikibot/logentries.py
M pywikibot/tools/__init__.py
M tests/logentry_tests.py
M tests/tools_tests.py
4 files changed, 65 insertions(+), 7 deletions(-)
Approvals:
Mpaa: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/logentries.py b/pywikibot/logentries.py
index 05607b6..031483c 100644
--- a/pywikibot/logentries.py
+++ b/pywikibot/logentries.py
@@ -14,7 +14,7 @@
import pywikibot
from pywikibot.exceptions import Error
-from pywikibot.tools import deprecated
+from pywikibot.tools import deprecated, classproperty
if sys.version_info[0] > 2:
basestring = (str, )
@@ -371,7 +371,7 @@
Only available method is create()
"""
- _logtypes = {
+ logtypes = {
'block': BlockEntry,
'protect': ProtectEntry,
'rights': RightsEntry,
@@ -403,6 +403,12 @@
logclass = LogEntryFactory._getEntryClass(logtype)
self._creator = lambda data: logclass(data, self._site)
+ @classproperty
+ @deprecated('LogEntryFactory.logtypes')
+ def _logtypes(cls): # flake8: disable=N805
+ """DEPRECATED LogEntryFactory class attribute of log types."""
+ return cls.logtypes
+
def create(self, logdata):
"""
Instantiate the LogEntry object representing logdata.
@@ -423,7 +429,7 @@
@rtype: class
"""
try:
- return cls._logtypes[logtype]
+ return cls.logtypes[logtype]
except KeyError:
return LogEntry
diff --git a/pywikibot/tools/__init__.py b/pywikibot/tools/__init__.py
index ffafbdf..2b7a0e1 100644
--- a/pywikibot/tools/__init__.py
+++ b/pywikibot/tools/__init__.py
@@ -169,6 +169,33 @@
return func
+class classproperty(object): # flake8: disable=N801
+
+ """
+ Metaclass to accesss a class method as a property.
+
+ This class may be used as a decorator::
+
+ class Foo(object):
+
+ _bar = 'baz' # a class property
+
+ @classproperty
+ def bar(cls): # a class property method
+ return cls._bar
+
+ Foo.bar gives 'baz'.
+ """
+
+ def __init__(self, cls_method):
+ """Hold the class method."""
+ self.method = cls_method
+
+ def __get__(self, instance, owner):
+ """Get the attribute of the owner class by its method."""
+ return self.method(owner)
+
+
class UnicodeMixin(object):
"""Mixin class to add __str__ method in Python 2 or 3."""
diff --git a/tests/logentry_tests.py b/tests/logentry_tests.py
index 20d8935..48646b6 100644
--- a/tests/logentry_tests.py
+++ b/tests/logentry_tests.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""Test logentries module."""
#
-# (C) Pywikibot team, 2015
+# (C) Pywikibot team, 2015-2016
#
# Distributed under the terms of the MIT license.
#
@@ -68,7 +68,7 @@
def _test_logevent(self, logtype):
"""Test a single logtype entry."""
logentry = self._get_logentry(logtype)
- if logtype in LogEntryFactory._logtypes:
+ if logtype in LogEntryFactory.logtypes:
self.assertEqual(logentry._expectedType, logtype)
else:
self.assertIsNone(logentry._expectedType)
@@ -110,7 +110,7 @@
return test_logevent
# create test methods for the support logtype classes
- for logtype in LogEntryFactory._logtypes:
+ for logtype in LogEntryFactory.logtypes:
cls.add_method(dct, 'test_%sEntry' % logtype.title(),
test_method(logtype))
@@ -136,7 +136,7 @@
# initialized yet.
available_types = set(self.site._paraminfo.parameter(
'query+logevents', 'type')['type'])
- for simple_type in available_types - set(LogEntryFactory._logtypes):
+ for simple_type in available_types - set(LogEntryFactory.logtypes):
if not simple_type:
# paraminfo also reports an empty string as a type
continue
diff --git a/tests/tools_tests.py b/tests/tools_tests.py
index c6525e9..7ddeaa6 100644
--- a/tests/tools_tests.py
+++ b/tests/tools_tests.py
@@ -23,6 +23,7 @@
mock = e
from pywikibot import tools
+from pywikibot.tools import classproperty
from tests import join_xml_data_path
@@ -724,6 +725,30 @@
self.chmod.assert_called_once_with(self.file, 0o600)
+class Foo(object):
+
+ """Test class to verify classproperty decorator."""
+
+ _bar = 'baz'
+
+ @classproperty
+ def bar(cls): # flake8: disable=N805
+ """Class property method."""
+ return cls._bar
+
+
+class TestClassProperty(TestCase):
+
+ """Test classproperty decorator."""
+
+ net = False
+
+ def test_classproperty(self):
+ """Test for classproperty decorator."""
+ self.assertEqual(Foo.bar, 'baz')
+ self.assertEqual(Foo.bar, Foo._bar)
+
+
if __name__ == '__main__': # pragma: no cover
try:
unittest.main()
--
To view, visit https://gerrit.wikimedia.org/r/311349
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I5467a59beb93372a89426b6bfaaca4cd38e71e57
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: Ladsgroup <Ladsgroup(a)gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
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: PageLoadInconsistentTitle exception for inconsistent page-loading results
......................................................................
PageLoadInconsistentTitle exception for inconsistent page-loading results
Errors for inconsistent page-loading results have been standardized.
Previously the same situation may have caused
"AttributeError: 'Page' object has no attribute '_pageid'"
which was harder to decipher. See T94826.
The new message does not include the method name itself; see
the stack trace instead.
Change-Id: I554417d81718158effe9bd3b1d233aa91a3464ef
---
M pywikibot/exceptions.py
M pywikibot/site.py
2 files changed, 37 insertions(+), 20 deletions(-)
Approvals:
Xqt: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/exceptions.py b/pywikibot/exceptions.py
index a59b69b..2f5adb5 100644
--- a/pywikibot/exceptions.py
+++ b/pywikibot/exceptions.py
@@ -32,6 +32,9 @@
- NotEmailableError: The target user has disabled email
- NoMoveTarget: An expected move target page does not exist
+PageLoadRelatedError: any exception which happens while loading a Page.
+ - InconsistentTitleReceived: Page receives a title inconsistent with query
+
PageSaveRelatedError: page exceptions within the save operation on a Page
(alias: PageNotSaved).
@@ -231,6 +234,30 @@
pass
+class PageLoadRelatedError(PageRelatedError):
+
+ """Loading the contents of a Page object has failed."""
+
+ message = u"Page %s was not loaded."
+
+
+class InconsistentTitleReceived(PageLoadRelatedError):
+
+ """Page receives a title inconsistent with query."""
+
+ def __init__(self, page, actual):
+ """Constructor.
+
+ @param page: Page that caused the exception
+ @type page: Page object
+ @param actual: title obtained by query
+ @type reason: basestring
+
+ """
+ self.message = "Query on %s returned data on '{0}'".format(actual)
+ super(InconsistentTitleReceived, self).__init__(page)
+
+
class SiteDefinitionError(Error): # noqa
"""Site does not exist"""
diff --git a/pywikibot/site.py b/pywikibot/site.py
index ce7f628..abbeb92 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -47,6 +47,7 @@
IsNotRedirectPage,
CircularRedirect,
InterwikiRedirectPage,
+ InconsistentTitleReceived,
LockedPage,
CascadeLockedPage,
LockedNoPage,
@@ -2862,14 +2863,11 @@
except api.APIError: # May occur if you are not logged in (no API read permissions).
return (0, 0, 0)
- def _update_page(self, page, query, method_name):
+ def _update_page(self, page, query):
for pageitem in query:
if not self.sametitle(pageitem['title'],
page.title(withSection=False)):
- pywikibot.warning(
- u"{0}: Query on {1} returned data on '{2}'".format(
- method_name, page, pageitem['title']))
- continue
+ raise InconsistentTitleReceived(page, pageitem['title'])
api.update_page(page, pageitem, query.props)
def loadpageinfo(self, page, preload=False):
@@ -2883,7 +2881,7 @@
type_arg="info",
titles=title.encode(self.encoding()),
inprop=inprop)
- self._update_page(page, query, 'loadpageinfo')
+ self._update_page(page, query)
def loadcoordinfo(self, page):
"""Load [[mw:Extension:GeoData]] info."""
@@ -2895,7 +2893,7 @@
'country', 'region',
'globe'],
coprimary='all')
- self._update_page(page, query, 'loadcoordinfo')
+ self._update_page(page, query)
def loadpageprops(self, page):
"""Load page props for the given page."""
@@ -2904,7 +2902,7 @@
type_arg="pageprops",
titles=title.encode(self.encoding()),
)
- self._update_page(page, query, 'loadpageprops')
+ self._update_page(page, query)
def loadimageinfo(self, page, history=False):
"""Load image info from api and save in page attributes.
@@ -2926,9 +2924,7 @@
# self._update_page() pattern and remove return
for pageitem in query:
if not self.sametitle(pageitem['title'], title):
- raise Error(
- u"loadimageinfo: Query on %s returned data on '%s'"
- % (page, pageitem['title']))
+ raise InconsistentTitleReceived(page, pageitem['title'])
api.update_page(page, pageitem, query.props)
if "imageinfo" not in pageitem:
@@ -3816,9 +3812,7 @@
for pagedata in rvgen:
if not self.sametitle(pagedata['title'],
page.title(withSection=False)):
- raise Error(
- u"loadrevisions: Query on %s returned data on '%s'"
- % (page, pagedata['title']))
+ raise InconsistentTitleReceived(page, pagedata['title'])
if "missing" in pagedata:
raise NoPage(page)
api.update_page(page, pagedata, rvgen.props)
@@ -3847,9 +3841,7 @@
total=total)
for pageitem in llquery:
if not self.sametitle(pageitem['title'], lltitle):
- raise Error(
- u"getlanglinks: Query on %s returned data on '%s'"
- % (page, pageitem['title']))
+ raise InconsistentTitleReceived(page, pageitem['title'])
if 'langlinks' not in pageitem:
continue
for linkdata in pageitem['langlinks']:
@@ -3870,9 +3862,7 @@
total=total)
for pageitem in elquery:
if not self.sametitle(pageitem['title'], eltitle):
- raise RuntimeError(
- "getlanglinks: Query on %s returned data on '%s'"
- % (page, pageitem['title']))
+ raise InconsistentTitleReceived(page, pageitem['title'])
if 'extlinks' not in pageitem:
continue
for linkdata in pageitem['extlinks']:
--
To view, visit https://gerrit.wikimedia.org/r/293957
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I554417d81718158effe9bd3b1d233aa91a3464ef
Gerrit-PatchSet: 7
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Whym <whym(a)whym.org>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Mpaa <mpaa.wiki(a)gmail.com>
Gerrit-Reviewer: MtDu <justin.d128(a)gmail.com>
Gerrit-Reviewer: Whym <whym(a)whym.org>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot <>