Source code for tests.namespace_tests

#!/usr/bin/env python3
"""Tests for the Namespace class."""
#
# (C) Pywikibot team, 2014-2022
#
# Distributed under the terms of the MIT license.
#
from __future__ import annotations

from collections.abc import Iterable
from contextlib import suppress

from pywikibot.site import Namespace, NamespacesDict
from pywikibot.site._namespace import BuiltinNamespace
from tests.aspects import TestCase, unittest


# 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()))


[docs] def builtin_NamespacesDict(): """Return a NamespacesDict of the builtin namespaces.""" return NamespacesDict(Namespace.builtin_namespaces())
[docs] class TestNamespaceObject(TestCase): """Test cases for Namespace class.""" net = False
[docs] def test_enums(self): """Test builtin namespace enum in Namespace.""" self.assertEqual(BuiltinNamespace.MAIN, 0) self.assertEqual(Namespace.MAIN, BuiltinNamespace.MAIN) self.assertEqual(Namespace.MEDIA, -2) self.assertGreater(Namespace.MAIN, Namespace.MEDIA) self.assertLess(Namespace.MEDIA, Namespace.MAIN) self.assertEqual(Namespace.CATEGORY, 14) self.assertGreater(Namespace.CATEGORY, Namespace.HELP_TALK)
[docs] def testNamespaceTypes(self): """Test cases for methods manipulating Namespace names.""" ns = Namespace.builtin_namespaces() self.assertIsInstance(ns, dict) for ns_number in range(16): self.assertIn(ns_number, ns) # Use a namespace object as a dict key self.assertEqual(ns[ns[ns_number]], ns[ns_number]) for key, value in ns.items(): self.assertIsInstance(key, int) self.assertIsInstance(value, Iterable) self.assertTrue(value) for name in value: self.assertIsInstance(name, str) self.assertEqual(ns[ns[key]], ns[key])
[docs] def testNamespaceConstructor(self): """Test Namespace constructor.""" kwargs = {'case': 'first-letter'} y = Namespace(id=6, custom_name='dummy', canonical_name='File', aliases=['Image', 'Immagine'], **kwargs) self.assertEqual(y.id, 6) self.assertEqual(y.custom_name, 'dummy') self.assertEqual(y.canonical_name, 'File') self.assertNotEqual(y.custom_name, 'Dummy') self.assertNotEqual(y.canonical_name, 'file') self.assertIn('Image', y.aliases) self.assertIn('Immagine', y.aliases) self.assertLength(y, 4) self.assertEqual(list(y), ['dummy', 'File', 'Image', 'Immagine']) self.assertEqual(y.case, 'first-letter')
[docs] def testNamespaceNameCase(self): """Namespace names are always case-insensitive.""" kwargs = {'case': 'first-letter'} y = Namespace(id=6, custom_name='dummy', canonical_name='File', aliases=['Image', 'Immagine'], **kwargs) self.assertIn('dummy', y) self.assertIn('Dummy', y) self.assertIn('file', y) self.assertIn('File', y) self.assertIn('image', y) self.assertIn('Image', y) self.assertIn('immagine', y) self.assertIn('Immagine', y)
[docs] def testNamespaceToString(self): """Test Namespace __str__.""" ns = Namespace.builtin_namespaces() self.assertEqual(str(ns[0]), ':') self.assertEqual(str(ns[1]), 'Talk:') self.assertEqual(str(ns[6]), ':File:') kwargs = {'case': 'first-letter'} y = Namespace(id=6, custom_name='ملف', canonical_name='File', aliases=['Image', 'Immagine'], **kwargs) self.assertEqual(str(y), ':File:') self.assertEqual(y.canonical_prefix(), ':File:') self.assertEqual(y.custom_prefix(), ':ملف:')
[docs] def testNamespaceCompare(self): """Test Namespace comparisons.""" a = Namespace(id=0, canonical_name='') self.assertEqual(a, 0) self.assertEqual(a, '') self.assertGreaterEqual(a, 0) self.assertLessEqual(a, 0) self.assertIsNotNone(a) self.assertGreater(a, -1) x = Namespace(id=6, custom_name='dummy', canonical_name='File', aliases=['Image', 'Immagine']) y = Namespace(id=6, custom_name='ملف', canonical_name='File', aliases=['Image', 'Immagine']) z = Namespace(id=7, custom_name='dummy 7', canonical_name='File', aliases=['Image', 'Immagine']) self.assertEqual(x, x) self.assertEqual(x, y) self.assertNotEqual(x, a) self.assertNotEqual(x, z) self.assertEqual(x, 6) self.assertEqual(x, 'dummy') self.assertEqual(x, 'Dummy') self.assertEqual(x, 'file') self.assertEqual(x, 'File') self.assertEqual(x, ':File') self.assertEqual(x, ':File:') self.assertEqual(x, 'File:') self.assertEqual(x, 'image') self.assertEqual(x, 'Image') self.assertGreaterEqual(x, 6) self.assertLessEqual(x, 6) self.assertEqual(y, 'ملف') self.assertLess(a, x) self.assertLess(x, z) self.assertLessEqual(a, x) self.assertGreater(x, a) self.assertGreater(x, 0) self.assertGreater(z, x) self.assertGreaterEqual(x, a) self.assertGreaterEqual(y, x) self.assertIn(6, [x, y, z]) self.assertNotIn(8, [x, y, z])
[docs] def testNamespaceNormalizeName(self): """Test Namespace.normalize_name.""" self.assertEqual(Namespace.normalize_name('File'), 'File') self.assertEqual(Namespace.normalize_name(':File'), 'File') self.assertEqual(Namespace.normalize_name('File:'), 'File') self.assertEqual(Namespace.normalize_name(':File:'), 'File') self.assertEqual(Namespace.normalize_name(''), '') self.assertEqual(Namespace.normalize_name(':'), False) self.assertEqual(Namespace.normalize_name('::'), False) self.assertEqual(Namespace.normalize_name(':::'), False) self.assertEqual(Namespace.normalize_name(':File::'), False) self.assertEqual(Namespace.normalize_name('::File:'), False) self.assertEqual(Namespace.normalize_name('::File::'), False)
[docs] def test_repr(self): """Test Namespace.__repr__.""" a = Namespace(id=0, canonical_name='Foo') s = repr(a) r = 'Namespace(id=0, custom_name={foo!r}, canonical_name={foo!r}, ' \ 'aliases=[])'.format(foo='Foo') self.assertEqual(s, r) a.defaultcontentmodel = 'bar' s = repr(a) r = ('Namespace(id=0, custom_name={foo!r}, canonical_name={foo!r}, ' 'aliases=[], defaultcontentmodel={bar!r})' .format(foo='Foo', bar='bar')) self.assertEqual(s, r) a.case = 'upper' s = repr(a) r = ('Namespace(id=0, custom_name={foo!r}, canonical_name={foo!r}, ' 'aliases=[], case={case!r}, defaultcontentmodel={bar!r})' .format(foo='Foo', case='upper', bar='bar')) self.assertEqual(s, r) b = eval(repr(a)) self.assertEqual(a, b)
[docs] class TestNamespaceCollections(TestCase): """Test how Namespace interact when in collections.""" net = False
[docs] def test_set(self): """Test converting sequence of Namespace to a set.""" namespaces = Namespace.builtin_namespaces() for key, value in namespaces.items(): self.assertIsInstance(key, int) self.assertIsInstance(value, Namespace) namespaces_set = set(namespaces) self.assertLength(namespaces, namespaces_set) for key in namespaces_set: self.assertIsInstance(key, int)
[docs] def test_set_minus(self): """Test performing set minus operation on set of Namespace objects.""" namespaces = Namespace.builtin_namespaces() excluded_namespaces = {-1, -2} positive_namespaces = set(namespaces) - excluded_namespaces self.assertLength(namespaces, len(positive_namespaces) + len(excluded_namespaces))
[docs] class TestNamespacesDictLookupName(TestCase): """Test NamespacesDict.lookup_name and lookup_normalized_name.""" net = False tests = { 4: ['project', 'PROJECT', 'Project', 'Project:'], 5: ['project talk', 'PROJECT TALK', 'Project talk', 'Project Talk:', 'project_talk', 'PROJECT_TALK', 'Project_talk', 'Project_Talk:'], }
[docs] def setUp(self): """Setup namespaces dict.""" super().setUp() self.namespaces = builtin_NamespacesDict()
[docs] def test_lookup_name(self): """Test lookup_name and getitem.""" for ns_id, values in self.tests.items(): for name in values: with self.subTest(name=name, ns_id=ns_id): # test lookup_name self.assertIs(self.namespaces.lookup_name(name), self.namespaces[ns_id]) # test __getitem__ self.assertEqual(self.namespaces[name].id, ns_id)
[docs] def test_getattr(self): """Test NamespacesDict.__getattr__.""" for ns_id, values in self.tests.items(): for name in values: if name.endswith(':') or ' ' in name: continue # no valid attribute but causes syntax error with self.subTest(name=name, ns_id=ns_id): if name.isupper(): result = eval(f'self.namespaces.{name}.id') self.assertEqual(result, ns_id) else: with self.assertRaises(AttributeError): exec(f'self.namespaces.{name}.id')
[docs] def test_lookup_normalized_name(self): """Test lookup_normalized_name.""" for ns_id, values in self.tests.items(): for name in values: with self.subTest(name=name, ns_id=ns_id): if name.islower() and '_' not in name: self.assertIs( self.namespaces.lookup_normalized_name(name), self.namespaces[ns_id]) else: self.assertIsNone( self.namespaces.lookup_normalized_name(name))
[docs] class TestNamespacesDictGetItem(TestCase): """Test NamespacesDict.__getitem__.""" VALIDNUMBER_RE = r'-?(0|[1-9]\d*)' EMPTYTEXT_RE = r'\s*' net = False
[docs] def test_ids(self): """Test lookup by canonical namespace id.""" namespaces = builtin_NamespacesDict() for namespace in namespaces.values(): self.assertEqual(namespace, namespaces[namespace.id])
[docs] def test_namespace(self): """Test lookup by Namespace object.""" namespaces = builtin_NamespacesDict() for namespace in namespaces.values(): self.assertEqual(namespace, namespaces[namespace])
[docs] def test_invalid_id(self): """Test lookup by invalid id.""" namespaces = builtin_NamespacesDict() lower = min(namespaces.keys()) - 1 higher = max(namespaces.keys()) + 1 with self.assertRaisesRegex(KeyError, self.VALIDNUMBER_RE): namespaces[lower] with self.assertRaisesRegex(KeyError, self.VALIDNUMBER_RE): namespaces[higher]
[docs] def test_canonical_name(self): """Test lookup by canonical namespace name.""" namespaces = builtin_NamespacesDict() for namespace in namespaces.values(): self.assertEqual(namespace, namespaces[namespace.canonical_name]) self.assertEqual(namespace, namespaces[namespace.canonical_name.upper()])
[docs] def test_canonical_attr(self): """Test attribute lookup by canonical namespace name.""" namespaces = builtin_NamespacesDict() self.assertEqual(namespaces[0], namespaces.MAIN) self.assertEqual(namespaces[1], namespaces.TALK) for namespace in namespaces.values(): if namespace.id == 0: continue attr = namespace.canonical_name.upper() self.assertEqual(namespace, getattr(namespaces, attr))
[docs] def test_all(self): """Test lookup by any namespace name.""" namespaces = builtin_NamespacesDict() for namespace in namespaces.values(): for name in namespace: self.assertEqual(namespace, namespaces[name.upper()])
[docs] def test_invalid_name(self): """Test lookup by invalid name.""" namespaces = builtin_NamespacesDict() with self.assertRaisesRegex(KeyError, self.EMPTYTEXT_RE): namespaces['FOO'] # '|' is not permitted in namespace names with self.assertRaisesRegex(KeyError, self.EMPTYTEXT_RE): namespaces['|']
if __name__ == '__main__': with suppress(SystemExit): unittest.main()