Build Update for wikimedia/pywikibot-core
-------------------------------------
Build: #2475
Status: Fixed
Duration: 23 minutes and 11 seconds
Commit: 901c746 (master)
Author: Yusuke Matsubara
Message: archivebot: consistent handling of on-site configuration errors
All ending of a run on a page will cause a sleep, with a configurable duration.
Previously a normal return from run() causes a 10-sec sleep,
while an exception causes no sleep and a stack trace will be printed.
Change-Id: I2cbb4026e331d0e23e07c1c8aef344ca194daaaa
View the changeset: https://github.com/wikimedia/pywikibot-core/compare/d8947234082c...901c7466…
View the full build log and details: https://travis-ci.org/wikimedia/pywikibot-core/builds/69515364
--
You can configure recipients for build notifications in your .travis.yml file. See http://docs.travis-ci.com/user/notifications
jenkins-bot has submitted this change and it was merged.
Change subject: archivebot: consistent handling of on-site configuration errors
......................................................................
archivebot: consistent handling of on-site configuration errors
All ending of a run on a page will cause a sleep, with a configurable duration.
Previously a normal return from run() causes a 10-sec sleep,
while an exception causes no sleep and a stack trace will be printed.
Change-Id: I2cbb4026e331d0e23e07c1c8aef344ca194daaaa
---
M scripts/archivebot.py
1 file changed, 21 insertions(+), 8 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/scripts/archivebot.py b/scripts/archivebot.py
index 1e82623..37ca904 100755
--- a/scripts/archivebot.py
+++ b/scripts/archivebot.py
@@ -112,12 +112,17 @@
ZERO = datetime.timedelta(0)
-class MalformedConfigError(pywikibot.Error):
+class ArchiveBotSiteConfigError(pywikibot.Error):
+
+ """There is an error originated by archivebot's on-site configuration."""
+
+
+class MalformedConfigError(ArchiveBotSiteConfigError):
"""There is an error in the configuration template."""
-class MissingConfigError(pywikibot.Error):
+class MissingConfigError(ArchiveBotSiteConfigError):
"""
The config is missing in the header.
@@ -131,7 +136,7 @@
"""Invalid specification of archiving algorithm."""
-class ArchiveSecurityError(pywikibot.Error):
+class ArchiveSecurityError(ArchiveBotSiteConfigError):
"""
Page title is not a valid archive of page being archived.
@@ -473,7 +478,7 @@
else:
raise MissingConfigError(u'Missing or malformed template')
if not self.get_attr('algo', ''):
- raise MissingConfigError(u'Missing algo')
+ raise MissingConfigError('Missing argument "algo" in template')
def feed_archive(self, archive, thread, max_archive_size, params=None):
"""Feed the thread to one of the archives.
@@ -554,8 +559,9 @@
rx = re.compile(r'\{\{%s\s*?\n.*?\n\}\}'
% (template_title_regex(self.tpl).pattern), re.DOTALL)
if not rx.search(self.page.header):
- pywikibot.error("Couldn't find the template in the header")
- return
+ raise MalformedConfigError(
+ "Couldn't find the template in the header"
+ )
pywikibot.output(u'Archiving %d thread(s).' % self.archived_threads)
# Save the archives first (so that bugs don't cause a loss of data)
@@ -595,6 +601,7 @@
salt = None
force = False
calc = None
+ sleep = 10
args = []
def if_arg_value(arg, name):
@@ -624,6 +631,8 @@
pagename = v
for v in if_arg_value(arg, '-namespace'):
namespace = v
+ for v in if_arg_value(arg, '-sleep'):
+ sleep = int(v)
if not arg.startswith('-'):
args.append(arg)
@@ -678,11 +687,15 @@
try:
archiver = PageArchiver(pg, a, salt, force)
archiver.run()
- time.sleep(10)
+ except ArchiveBotSiteConfigError as e:
+ # no stack trace for errors originated by pages on-site
+ pywikibot.error('Missing or malformed template in page %s: %s'
+ % (pg, e))
except Exception:
pywikibot.error(u'Error occurred while processing page %s' % pg)
pywikibot.exception(tb=True)
-
+ finally:
+ time.sleep(sleep)
if __name__ == '__main__':
main()
--
To view, visit https://gerrit.wikimedia.org/r/222727
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I2cbb4026e331d0e23e07c1c8aef344ca194daaaa
Gerrit-PatchSet: 3
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Whym <whym(a)whym.org>
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: Changing the sandbox content template on Fa WP
......................................................................
Changing the sandbox content template on Fa WP
Bug: T104716
Change-Id: I24824713adedd3135cc5377141d2443e15dc0fd6
---
M scripts/clean_sandbox.py
1 file changed, 1 insertion(+), 1 deletion(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/scripts/clean_sandbox.py b/scripts/clean_sandbox.py
index 527da31..b6d9824 100755
--- a/scripts/clean_sandbox.py
+++ b/scripts/clean_sandbox.py
@@ -63,7 +63,7 @@
u'and editing skills below this line. As this page is for editing '
u'experiments, this page will automatically be cleaned every 12 '
u'hours. -->',
- 'fa': u'{{subst:User:Amirobot/sandbox}}',
+ 'fa': u'{{subst:Wikipedia:ربات/sandbox}}',
'fi': u'{{subst:Hiekka}}',
'he': u'{{ארגז חול}}\n<!-- נא לערוך מתחת לשורה זו בלבד, תודה. -->',
'id': u'{{Bakpasir}}\n<!-- Uji coba dilakukan di baris di bawah ini -->',
--
To view, visit https://gerrit.wikimedia.org/r/222696
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I24824713adedd3135cc5377141d2443e15dc0fd6
Gerrit-PatchSet: 2
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Huji <huji.huji(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] NamespacesDict to replace Namespace methods
......................................................................
[FEAT] NamespacesDict to replace Namespace methods
Instead of having static/classmethods in Namespace use a dict which stores the
Namespace instances and allows general handling of them. This reuses the
_NamespacesDict introduced in ae69d8dc. This makes doing lookups easier as it's
not necessary to import the Namespace class and having to manually define on
which namespaces it works.
This makes also ns_index unnecessary as it's relatively easy possible to
actually get the Namespace using the name and a site instance now.
It also adds a new TestCase class which patches assert calls to easily check if
the deprecation message was issued after each assertion.
Change-Id: I74507af6f22cf09fa161f5df07e1dd90cb399759
---
M pywikibot/data/api.py
M pywikibot/page.py
M pywikibot/pagegenerators.py
M pywikibot/site.py
M scripts/templatecount.py
M tests/aspects.py
M tests/namespace_tests.py
M tests/site_tests.py
M tests/wikibase_tests.py
9 files changed, 254 insertions(+), 116 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/data/api.py b/pywikibot/data/api.py
index 3e5d960..9549e46 100644
--- a/pywikibot/data/api.py
+++ b/pywikibot/data/api.py
@@ -2348,8 +2348,7 @@
# Use Namespace id (int) here; Request will cast int to str
namespaces = [ns.id for ns in
- pywikibot.site.Namespace.resolve(namespaces,
- self.site.namespaces)]
+ self.site.namespaces.resolve(namespaces)]
if 'multi' not in param and len(namespaces) != 1:
raise TypeError(u'{0} module does not support multiple namespaces'
diff --git a/pywikibot/page.py b/pywikibot/page.py
index b47badd..69a1c02 100644
--- a/pywikibot/page.py
+++ b/pywikibot/page.py
@@ -4678,7 +4678,7 @@
t = t.lstrip(u":").lstrip(u" ")
continue
prefix = t[:t.index(u":")].lower() # part of text before :
- ns = self._source.ns_index(prefix)
+ ns = self._source.namespaces.lookup_name(prefix)
if ns:
# The prefix is a namespace in the source wiki
return (fam.name, code)
@@ -4719,7 +4719,7 @@
continue
prefix = t[:t.index(u":")].lower()
- ns = self._site.ns_index(prefix)
+ ns = self._site.namespaces.lookup_name(prefix)
if ns:
# Ordinary namespace
t = t[t.index(u":"):].lstrip(u":").lstrip(u" ")
@@ -4765,7 +4765,7 @@
self._namespace + 1]
if '' in other_ns: # other namespace uses empty str as ns
next_ns = t[:t.index(':')]
- if self._site.ns_index(next_ns):
+ if self._site.namespaces.lookup_name(next_ns):
raise pywikibot.InvalidTitle(
u"The (non-)talk page of '{0}' is a valid title "
"in another namespace.".format(self._text))
@@ -4890,7 +4890,7 @@
else:
# look for corresponding ns in onsite by name comparison
for alias in ns:
- namespace = Namespace.lookup_name(alias, onsite.namespaces)
+ namespace = onsite.namespaces.lookup_name(alias)
if namespace:
namespace = namespace.custom_name
break
@@ -5018,7 +5018,7 @@
if ':' in title:
ns, t = title.split(':', 1)
- ns = link._site.ns_index(ns.lower())
+ ns = link._site.namespaces.lookup_name(ns)
if ns:
link._namespace = ns
title = t
diff --git a/pywikibot/pagegenerators.py b/pywikibot/pagegenerators.py
index df3382c..fe51ab1 100644
--- a/pywikibot/pagegenerators.py
+++ b/pywikibot/pagegenerators.py
@@ -47,7 +47,6 @@
from pywikibot.comms import http
from pywikibot.data import wikidataquery as wdquery
from pywikibot.exceptions import ArgumentDeprecationWarning
-from pywikibot.site import Namespace
if sys.version_info[0] > 2:
basestring = (str, )
@@ -355,7 +354,7 @@
"""
if isinstance(self._namespaces, list):
self._namespaces = frozenset(
- Namespace.resolve(self._namespaces, self.site.namespaces))
+ self.site.namespaces.resolve(self._namespaces))
return self._namespaces
def getCombinedGenerator(self, gen=None):
@@ -1208,10 +1207,10 @@
# As site was only required if the namespaces contain strings, dont
# attempt to use the config selected site unless the initial attempt
# at resolving the namespaces fails.
+ if not site:
+ site = pywikibot.Site()
try:
- namespaces = Namespace.resolve(namespaces,
- site.namespaces if site else
- pywikibot.Site().namespaces)
+ namespaces = site.namespaces.resolve(namespaces)
except KeyError as e:
pywikibot.log('Failed resolving namespaces:')
pywikibot.exception(e)
diff --git a/pywikibot/site.py b/pywikibot/site.py
index c4d53ce..b361d61 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -26,13 +26,13 @@
import copy
import mimetypes
-from collections import Iterable, Container, namedtuple
+from collections import Iterable, Container, namedtuple, Mapping
from warnings import warn
import pywikibot
import pywikibot.family
from pywikibot.tools import (
- itergroup, UnicodeMixin, ComparableMixin, SelfCallDict, SelfCallString,
+ itergroup, UnicodeMixin, ComparableMixin, SelfCallMixin, SelfCallString,
deprecated, deprecate_arg, deprecated_args, remove_last_args,
redirect_func, issue_deprecation_warning,
manage_wrapping, MediaWikiVersion, first_upper, normalize_username,
@@ -414,6 +414,7 @@
return False
@classmethod
+ @deprecated('NamespacesDict.lookup_name')
def lookup_name(cls, name, namespaces=None):
"""Find the Namespace for a name.
@@ -427,18 +428,10 @@
if not namespaces:
namespaces = cls.builtin_namespaces()
- name = cls.normalize_name(name)
- if name is False:
- return None
- name = name.lower()
-
- for namespace in namespaces.values():
- if namespace._contains_lowercase_name(name):
- return namespace
-
- return None
+ return NamespacesDict._lookup_name(name, namespaces)
@staticmethod
+ @deprecated('NamespacesDict.resolve')
def resolve(identifiers, namespaces=None):
"""
Resolve namespace identifiers to obtain Namespace objects.
@@ -461,6 +454,83 @@
if not namespaces:
namespaces = Namespace.builtin_namespaces()
+ return NamespacesDict._resolve(identifiers, namespaces)
+
+
+class NamespacesDict(Mapping, SelfCallMixin):
+
+ """
+ An immutable dictionary containing the Namespace instances.
+
+ It adds a deprecation message when called as the 'namespaces' property of
+ APISite was callable.
+ """
+
+ _own_desc = 'the namespaces property'
+
+ def __init__(self, namespaces):
+ """Create new dict using the given namespaces."""
+ super(NamespacesDict, self).__init__()
+ self._namespaces = namespaces
+
+ def __iter__(self):
+ """Iterate over all namespaces."""
+ return iter(self._namespaces)
+
+ def __getitem__(self, number):
+ """Get the namespace with the given number."""
+ return self._namespaces[number]
+
+ def __len__(self):
+ """Get the number of namespaces."""
+ return len(self._namespaces)
+
+ def lookup_name(self, name):
+ """
+ Find the Namespace for a name also checking aliases.
+
+ @param name: Name of the namespace.
+ @type name: basestring
+ @return: Namespace or None
+ """
+ return self._lookup_name(name, self._namespaces)
+
+ # Temporary until Namespace.lookup_name can be removed
+ @staticmethod
+ def _lookup_name(name, namespaces):
+ name = Namespace.normalize_name(name)
+ if name is False:
+ return None
+ name = name.lower()
+
+ for namespace in namespaces.values():
+ if namespace._contains_lowercase_name(name):
+ return namespace
+
+ return None
+
+ def resolve(self, identifiers):
+ """
+ Resolve namespace identifiers to obtain Namespace objects.
+
+ Identifiers may be any value for which int() produces a valid
+ namespace id, except bool, or any string which Namespace.lookup_name
+ successfully finds. A numerical string is resolved as an integer.
+
+ @param identifiers: namespace identifiers
+ @type identifiers: iterable of basestring or Namespace key,
+ or a single instance of those types
+ @return: list of Namespace objects in the same order as the
+ identifiers
+ @raises KeyError: a namespace identifier was not resolved
+ @raises TypeError: a namespace identifier has an inappropriate
+ type such as NoneType or bool
+ """
+ return self._resolve(identifiers, self._namespaces)
+
+ # Temporary until Namespace.resolve can be removed
+ @staticmethod
+ def _resolve(identifiers, namespaces):
if isinstance(identifiers, (basestring, Namespace)):
identifiers = [identifiers]
else:
@@ -473,7 +543,7 @@
# lookup namespace names, and assume anything else is a key.
# int(None) raises TypeError; however, bool needs special handling.
result = [NotImplemented if isinstance(ns, bool) else
- Namespace.lookup_name(ns, namespaces)
+ NamespacesDict._lookup_name(ns, namespaces)
if isinstance(ns, basestring) and
not ns.lstrip('-').isdigit() else
namespaces[int(ns)] if int(ns) in namespaces
@@ -492,14 +562,6 @@
if ns is None]))
return result
-
-
-# This class can be removed after self-callability has been removed
-class _NamespacesDict(SelfCallDict):
-
- """A wrapper to add a deprecation message when called."""
-
- _own_desc = 'the namespaces property'
class BaseSite(ComparableMixin):
@@ -787,6 +849,7 @@
self.interwiki(prefix)
return self._iw_sites[prefix][1]
+ @deprecated('APISite.namespaces.lookup_name')
def ns_index(self, namespace):
"""
Return the Namespace for a given namespace name.
@@ -796,11 +859,12 @@
@return: The matching Namespace object on this Site
@rtype: Namespace, or None if invalid
"""
- return Namespace.lookup_name(namespace, self.namespaces)
+ return self.namespaces.lookup_name(namespace)
- # for backwards-compatibility
- getNamespaceIndex = redirect_func(ns_index, old_name='getNamespaceIndex',
- class_name='BaseSite')
+ @deprecated('APISite.namespaces.lookup_name')
+ def getNamespaceIndex(self, namespace):
+ """DEPRECATED: Return the Namespace for a given namespace name."""
+ return self.namespaces.lookup_name(namespace)
def _build_namespaces(self):
"""Create default namespaces."""
@@ -811,7 +875,7 @@
def namespaces(self):
"""Return dict of valid namespaces on this wiki."""
if not hasattr(self, '_namespaces'):
- self._namespaces = _NamespacesDict(self._build_namespaces())
+ self._namespaces = NamespacesDict(self._build_namespaces())
return self._namespaces
def ns_normalize(self, value):
@@ -821,7 +885,7 @@
@type value: unicode
"""
- index = self.ns_index(value)
+ index = self.namespaces.lookup_name(value)
return self.namespace(index)
# for backwards-compatibility
@@ -938,7 +1002,7 @@
"""Separate the namespace from the name."""
ns, delim, name = title.partition(':')
if delim:
- ns = Namespace.lookup_name(ns, self.namespaces)
+ ns = self.namespaces.lookup_name(ns)
if not delim or not ns:
return default_ns, title
else:
diff --git a/scripts/templatecount.py b/scripts/templatecount.py
index 5751641..f875627 100755
--- a/scripts/templatecount.py
+++ b/scripts/templatecount.py
@@ -98,7 +98,7 @@
mysite = pywikibot.Site()
# The names of the templates are the keys, and lists of pages
# transcluding templates are the values.
- mytpl = mysite.ns_index(mysite.template_namespace())
+ mytpl = mysite.namespaces.lookup_name(mysite.template_namespace())
for template in templates:
transcludingArray = []
gen = pywikibot.Page(mysite, template, ns=mytpl).getReferences(
diff --git a/tests/aspects.py b/tests/aspects.py
index 3e6f6c2..8bd4553 100644
--- a/tests/aspects.py
+++ b/tests/aspects.py
@@ -37,6 +37,8 @@
import time
import warnings
+from contextlib import contextmanager
+
import pywikibot
from pywikibot import config, log, ServerError, Site
@@ -937,6 +939,58 @@
return page
+class CapturingTestCase(TestCase):
+
+ """
+ Capture assertion calls to do additional calls around them.
+
+ All assertions done which start with "assert" are patched in such a way that
+ after the assertion it calls C{process_assertion} with the assertion and the
+ arguments.
+
+ To avoid that it patches the assertion it's possible to put the call in an
+ C{disable_assert_capture} with-statement.
+
+ """
+
+ # Is True while an assertion is running, so that assertions won't be patched
+ # when they are executed while an assertion is running and only the outer
+ # most assertion gets actually patched.
+ _patched = False
+
+ @contextmanager
+ def disable_assert_capture(self):
+ """A context manager which preventing that asssertions are patched."""
+ nested = self._patched # Don't reset if it was set before
+ self._patched = True
+ yield
+ if not nested:
+ self._patched = False
+
+ def process_assert(self, assertion, *args, **kwargs):
+ """Handle the assertion."""
+ assertion(*args, **kwargs)
+
+ def patch_assert(self, assertion):
+ """Execute process_assert when the assertion is called."""
+ def inner_assert(*args, **kwargs):
+ assert self._patched is False
+ self._patched = True
+ try:
+ self.process_assert(assertion, *args, **kwargs)
+ finally:
+ self._patched = False
+ return inner_assert
+
+ def __getattribute__(self, attr):
+ """Patch assertions if enabled."""
+ result = super(CapturingTestCase, self).__getattribute__(attr)
+ if attr.startswith('assert') and not self._patched:
+ return self.patch_assert(result)
+ else:
+ return result
+
+
class SiteAttributeTestCase(TestCase):
"""Add the sites as attributes to the instances."""
@@ -1273,6 +1327,13 @@
if self._do_test_warning_filename:
self.assertDeprecationFile(self.expect_warning_filename)
+ def assertOneDeprecation(self, msg=None, reset=True):
+ """Assert that exactly one deprecation happened and reset if wished."""
+ self.assertEqual(len(self.deprecation_messages), 1)
+ self.assertDeprecation(msg)
+ if reset:
+ self._reset_messages()
+
def assertNoDeprecation(self, msg=None):
if msg:
self.assertNotIn(msg, self.deprecation_messages)
@@ -1299,3 +1360,29 @@
self.context_manager.__exit__()
super(DeprecationTestCase, self).tearDown()
+
+
+class AutoDeprecationTestCase(CapturingTestCase, DeprecationTestCase):
+
+ """
+ A test case capturing asserts and asserting a deprecation afterwards.
+
+ For example C{assertEqual} will do first C{assertEqual} and then
+ C{assertOneDeprecation}.
+
+ With C{check_file} it's possible to enable or disable the check whether the
+ filename matches the caller's filename. By default it does not match the
+ filename if the name starts with 'assertRaises' (as it'll call it inside the
+ assert in that case).
+ """
+
+ def process_assert(self, assertion, *args, **kwargs):
+ """Handle assertion and call C{assertOneDeprecation} after it."""
+ super(AutoDeprecationTestCase, self).process_assert(
+ assertion, *args, **kwargs)
+ self._do_test_warning_filename = self.check_file(assertion.__name__)
+ self.assertOneDeprecation()
+
+ def check_file(self, name):
+ """Disable filename check on asserted exceptions."""
+ return not name.startswith('assertRaises')
diff --git a/tests/namespace_tests.py b/tests/namespace_tests.py
index 6f18a73..1638114 100644
--- a/tests/namespace_tests.py
+++ b/tests/namespace_tests.py
@@ -11,12 +11,39 @@
from collections import Iterable
from pywikibot.site import Namespace
-from tests.aspects import unittest, TestCase
+from tests.aspects import unittest, TestCase, AutoDeprecationTestCase
import sys
if sys.version_info[0] > 2:
basestring = (str, )
unicode = str
+
+# Default namespaces which should work in any MW wiki
+_base_builtin_ns = {
+ 'Media': -2,
+ 'Special': -1,
+ '': 0,
+ 'Talk': 1,
+ 'User': 2,
+ 'User talk': 3,
+ 'Project': 4,
+ 'Project talk': 5,
+ 'MediaWiki': 8,
+ 'MediaWiki talk': 9,
+ 'Template': 10,
+ 'Template talk': 11,
+ 'Help': 12,
+ 'Help talk': 13,
+ 'Category': 14,
+ 'Category talk': 15,
+}
+image_builtin_ns = dict(_base_builtin_ns)
+image_builtin_ns['Image'] = 6
+image_builtin_ns['Image talk'] = 7
+file_builtin_ns = dict(_base_builtin_ns)
+file_builtin_ns['File'] = 6
+file_builtin_ns['File talk'] = 7
+builtin_ns = dict(list(image_builtin_ns.items()) + list(file_builtin_ns.items()))
class TestNamespaceObject(TestCase):
@@ -24,35 +51,6 @@
"""Test cases for Namespace class."""
net = False
-
- # These should work in any MW wiki
- builtin_ids = {
- 'Media': -2,
- 'Special': -1,
- '': 0,
- 'Talk': 1,
- 'User': 2,
- 'User talk': 3,
- 'Project': 4,
- 'Project talk': 5,
- 'File': 6,
- 'File talk': 7,
- 'MediaWiki': 8,
- 'MediaWiki talk': 9,
- 'Template': 10,
- 'Template talk': 11,
- 'Help': 12,
- 'Help talk': 13,
- 'Category': 14,
- 'Category talk': 15,
- }
-
- old_builtin_ids = {
- 'Image': 6,
- 'Image talk': 7,
- }
-
- all_builtin_ids = dict(list(builtin_ids.items()) + list(old_builtin_ids.items()))
def testNamespaceTypes(self):
"""Test cases for methods manipulating namespace names."""
@@ -68,20 +66,6 @@
self.assertTrue(all(isinstance(name, basestring)
for val in ns.values()
for name in val))
-
- self.assertTrue(all(isinstance(Namespace.lookup_name(b, ns), Namespace)
- for b in self.builtin_ids))
-
- self.assertTrue(all(Namespace.lookup_name(b, ns).id == self.all_builtin_ids[b]
- for b in self.all_builtin_ids))
-
- ns = Namespace.builtin_namespaces(use_image_name=True)
-
- self.assertTrue(all(isinstance(Namespace.lookup_name(b, ns), Namespace)
- for b in self.builtin_ids))
-
- self.assertTrue(all(Namespace.lookup_name(b, ns).id == self.all_builtin_ids[b]
- for b in self.all_builtin_ids))
# Use a namespace object as a dict key
self.assertEqual(ns[ns[6]], ns[6])
@@ -218,6 +202,13 @@
b = eval(repr(a))
self.assertEqual(a, b)
+
+class TestNamespaceDictDeprecated(AutoDeprecationTestCase):
+
+ """Test static/classmethods in Namespace replaced by NamespacesDict."""
+
+ net = False
+
def test_resolve(self):
"""Test Namespace.resolve."""
namespaces = Namespace.builtin_namespaces(use_image_name=False)
@@ -276,6 +267,20 @@
r'Namespace identifier\(s\) not recognised: -10,-11',
Namespace.resolve, [-10, 0, -11])
+ def test_lookup_name(self):
+ """Test Namespace.lookup_name."""
+ file_nses = Namespace.builtin_namespaces(use_image_name=False)
+ image_nses = Namespace.builtin_namespaces(use_image_name=True)
+
+ for name, ns_id in builtin_ns.items():
+ file_ns = Namespace.lookup_name(name, file_nses)
+ self.assertIsInstance(file_ns, Namespace)
+ image_ns = Namespace.lookup_name(name, image_nses)
+ self.assertIsInstance(image_ns, Namespace)
+ with self.disable_assert_capture():
+ self.assertEqual(file_ns.id, ns_id)
+ self.assertEqual(image_ns.id, ns_id)
+
class TestNamespaceCollections(TestCase):
diff --git a/tests/site_tests.py b/tests/site_tests.py
index 7b25577..e5497d8 100644
--- a/tests/site_tests.py
+++ b/tests/site_tests.py
@@ -12,7 +12,7 @@
import sys
import os
-from collections import Iterable
+from collections import Iterable, Mapping
from datetime import datetime
import re
@@ -120,6 +120,11 @@
for page in self.site.allpages(filterredir='', total=1):
self.assertFalse(page.isRedirectPage())
self.assertDeprecation()
+
+ def test_ns_index(self):
+ """Test ns_index."""
+ self.assertEqual(self.site.ns_index('MediaWiki'), 8)
+ self.assertOneDeprecation()
class TestSiteDryDeprecatedFunctions(DefaultDrySiteTestCase, DeprecationTestCase):
@@ -257,28 +262,8 @@
def testNamespaceMethods(self):
"""Test cases for methods manipulating namespace names."""
mysite = self.get_site()
- builtins = {
- '': 0, # these should work in any MW wiki
- 'Talk': 1,
- 'User': 2,
- 'User talk': 3,
- 'Project': 4,
- 'Project talk': 5,
- 'Image': 6,
- 'Image talk': 7,
- 'MediaWiki': 8,
- 'MediaWiki talk': 9,
- 'Template': 10,
- 'Template talk': 11,
- 'Help': 12,
- 'Help talk': 13,
- 'Category': 14,
- 'Category talk': 15,
- }
- self.assertTrue(all(mysite.ns_index(b) == builtins[b]
- for b in builtins))
ns = mysite.namespaces
- self.assertIsInstance(ns, dict)
+ self.assertIsInstance(ns, Mapping)
self.assertTrue(all(x in ns for x in range(0, 16)))
# built-in namespaces always present
self.assertIsInstance(mysite.ns_normalize("project"), basestring)
@@ -1006,7 +991,7 @@
title = change['title']
self.assertIn(":", title)
prefix = title[:title.index(":")]
- self.assertIn(mysite.ns_index(prefix), [6, 7])
+ self.assertIn(self.site.namespaces.lookup_name(prefix).id, [6, 7])
self.assertIn(change["ns"], [6, 7])
if MediaWikiVersion(mysite.version()) <= MediaWikiVersion("1.14"):
pagelist = [mainpage]
@@ -1248,7 +1233,7 @@
title = rev['title']
self.assertIn(":", title)
prefix = title[:title.index(":")]
- self.assertIn(mysite.ns_index(prefix), [6, 7])
+ self.assertIn(self.site.namespaces.lookup_name(prefix).id, [6, 7])
self.assertIn(rev["ns"], [6, 7])
for rev in mysite.watchlist_revs(showMinor=True, total=5):
self.assertIsInstance(rev, dict)
@@ -2525,7 +2510,7 @@
site = self.get_site('wikia')
self.assertEqual(site.hostname(), 'www.wikia.com')
self.assertEqual(site.code, 'wikia')
- self.assertIsInstance(site.namespaces, dict)
+ self.assertIsInstance(site.namespaces, Mapping)
self.assertFalse(site.obsolete)
self.assertEqual(site.family.hostname('en'), 'www.wikia.com')
self.assertEqual(site.family.hostname('wikia'), 'www.wikia.com')
@@ -2558,7 +2543,7 @@
site = self.get_site('lyricwiki')
self.assertEqual(site.hostname(), 'lyrics.wikia.com')
self.assertEqual(site.code, 'en')
- self.assertIsInstance(site.namespaces, dict)
+ self.assertIsInstance(site.namespaces, Mapping)
self.assertFalse(site.obsolete)
self.assertEqual(site.family.hostname('en'), 'lyrics.wikia.com')
@@ -2576,7 +2561,7 @@
site = self.get_site('commons')
self.assertEqual(site.hostname(), 'commons.wikimedia.org')
self.assertEqual(site.code, 'commons')
- self.assertIsInstance(site.namespaces, dict)
+ self.assertIsInstance(site.namespaces, Mapping)
self.assertFalse(site.obsolete)
self.assertRaises(KeyError, site.family.hostname, 'en')
@@ -2608,7 +2593,7 @@
site = self.get_site('wikidata')
self.assertEqual(site.hostname(), 'www.wikidata.org')
self.assertEqual(site.code, 'wikidata')
- self.assertIsInstance(site.namespaces, dict)
+ self.assertIsInstance(site.namespaces, Mapping)
self.assertFalse(site.obsolete)
self.assertRaises(KeyError, site.family.hostname, 'en')
diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py
index bbac998..0c9bb28 100644
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -17,9 +17,8 @@
import pywikibot
from pywikibot import pagegenerators
-from pywikibot.tools import SelfCallDict
from pywikibot.page import WikibasePage, ItemPage
-from pywikibot.site import Namespace
+from pywikibot.site import Namespace, NamespacesDict
from tests.aspects import (
unittest, TestCase,
@@ -842,7 +841,7 @@
def setUpClass(cls):
super(TestAlternateNamespaces, cls).setUpClass()
- cls.get_repo()._namespaces = SelfCallDict({
+ cls.get_repo()._namespaces = NamespacesDict({
90: Namespace(id=90,
case='first-letter',
canonical_name='Item',
--
To view, visit https://gerrit.wikimedia.org/r/221560
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I74507af6f22cf09fa161f5df07e1dd90cb399759
Gerrit-PatchSet: 5
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 <>